From 9d29be7f7249789d6ffd0440067187a9f040c2cd Mon Sep 17 00:00:00 2001 From: huangcm <1263938474@qq.com> Date: Wed, 18 Dec 2024 03:25:06 +0000 Subject: [PATCH] feat(4g): Compatible with ec20 and ec200 --- android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl | 1015 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h | 92 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl | 48 android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c | 293 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff | 7 android/external/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim | 104 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e | 3 android/external/usb_modeswitch/usb_modeswitch/Makefile | 105 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-index | 70 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c | 137 android/external/usb_modeswitch/usb_modeswitch/jim/jim-array.c | 274 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-package.c | 259 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 | 4 android/external/usb_modeswitch/usb_modeswitch/Android.mk | 21 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf | 31 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 | 4 android/external/usb_modeswitch/usb_modeswitch/COPYING | 340 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service | 8 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess | 1508 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Makefile | 105 android/external/usb_modeswitch/usb_modeswitch/ChangeLog | 288 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 | 5 android/external/usb_modeswitch/usb_dongle/NetlinkManager.h | 48 android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.h | 117 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.cpp | 89 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/Makefile.in | 198 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb | 2 android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.c | 1756 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/ChangeLog | 288 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f | 4 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-up | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl | 1015 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c | 2 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt | 87 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 | 3 android/external/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl | 48 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/auto.def | 436 android/external/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h | 69 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce | 4 android/external/usb_modeswitch/usb_modeswitch/README | 271 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 | 4 android/external/usb_modeswitch/usb_dongle/G3Dev.cpp | 206 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt | 84 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 | 4 android/external/usb_modeswitch/usb_dongle/MiscManager.cpp | 89 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 | 2 android/external/usb_modeswitch/usb_modeswitch/CleanSpec.mk | 53 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-format.c | 433 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 | 7 android/device/softwinner/common/sepolicy/vendor/rild.te | 56 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-ndk.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-readline.c | 61 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt | 88 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 | 4 android/vendor/aw/public/prebuild/lib/librild/radio_common.mk | 122 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Android.mk | 21 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl | 279 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt | 73 android/external/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c | 234 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 | 6 android/external/usb_modeswitch/usb_modeswitch/jim/jim-clock.c | 159 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 | 8 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jimsh.c | 111 android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h | 275 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/LICENSE | 45 android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c | 338 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 | 6 android/external/usb_modeswitch/usb_dongle/Misc.h | 43 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 | 6 android/external/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl | 38 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 | 6 android/external/usb_modeswitch/usb_modeswitch/jim/tree.tcl | 219 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 | 6 android/external/usb_modeswitch/usb_dongle/NetlinkManager.cpp | 113 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl | 45 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_#android | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/regtest.tcl | 158 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl | 27 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 | 21 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl | 150 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readline.c | 61 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt | 85 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a | 6 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-down | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl | 38 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/COPYING | 340 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_#linux | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimsh.c | 111 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff | 4 android/hardware/ril/libril/Android.mk | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-array.c | 274 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff | 5 android/external/usb_modeswitch/usb_modeswitch/jim/AUTHORS | 41 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.h | 43 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b | 2 android/external/usb_modeswitch/usb_modeswitch/jim/make-index | 70 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h | 69 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 | 2 android/external/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 | 2 android/external/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c | 190 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage | 3 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl | 63 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.h | 34 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff | 5 android/external/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/README | 271 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in | 145 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 | 8 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c | 119 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh | 17 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub | 1739 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c | 190 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 | 6 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt | 65 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.cpp | 69 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c | 760 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h | 87 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/usb_dongle.rc | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-aio.c | 1353 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/apns-full-conf.xml | 35501 ++++++++++++++++ android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt | 65 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_#android | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.c | 514 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.h | 24 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 | 5 android/external/usb_modeswitch/usb_dongle/main.cpp | 139 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 | 2 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an10.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 | 4 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/manifest.xml | 12 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-clock.c | 159 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd | 4 android/external/usb_modeswitch/usb_dongle/MiscManager.h | 57 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c | 293 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/configure | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h | 92 android/hardware/ril/rild/Android.mk | 2 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Android.mk | 47 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-package.c | 259 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 | 3 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt | 84 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.c | 1379 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup | 1820 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.h | 62 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.c | 192 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.h | 110 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 | 4 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/chat | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df | 2 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-ndk.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl | 268 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl | 150 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/README | 235 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f | 4 android/external/usb_modeswitch/usb_dongle/G3Dev.h | 38 android/vendor/aw/public/prebuild/lib/librild/libquecte/Android.mk | 43 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl | 63 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.h | 117 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.c | 1756 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl | 660 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-format.c | 433 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 | 4 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an12.so | 0 android/external/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl | 3 android/external/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c | 566 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup | 1820 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl | 279 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 | 6 android/external/usb_modeswitch/usb_dongle/NetlinkHandler.h | 34 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf | 31 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h | 275 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c | 338 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup | 1 android/external/usb_modeswitch/usb_modeswitch/jim/jim-aio.c | 1353 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-file.c | 929 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in | 145 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure.ac | 1 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl | 64 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.h | 917 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.c | 14478 ++++++ android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_#linux | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/dispatcher.c | 88 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-pack.c | 380 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub | 1739 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl | 27 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.h | 57 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/regtest.tcl | 158 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.cpp | 59 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt | 87 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess | 1508 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-posix.c | 231 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim | 104 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt | 73 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 | 4 longan/kernel/linux-4.9/drivers/usb/serial/option.c | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.c | 1379 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.h | 62 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/AUTHORS | 41 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_#linux | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f | 7 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/call-pppd | 34 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c | 566 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d | 7 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE | 35 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d | 2 android/external/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c | 137 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 | 5 android/external/usb_modeswitch/usb_dongle/usb_dongle.rc | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt | 65 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl | 77 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/main.cpp | 139 android/external/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c | 119 android/external/usb_modeswitch/usb_modeswitch/jim/utf8.h | 110 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.cpp | 206 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 | 6 android/external/usb_modeswitch/usb_modeswitch/jim/utf8.c | 192 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README | 235 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 | 4 android/external/usb_modeswitch/CleanSpec.mk | 53 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c | 234 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms | 40 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 | 172 android/external/usb_modeswitch/usb_modeswitch/jim/jim-load.c | 126 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 | 2 android/external/usb_modeswitch/usb_modeswitch/jim/Makefile.in | 198 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 | 5 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an10.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl | 660 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.c | 2095 android/external/usb_modeswitch/usb_dongle/Misc.cpp | 69 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.h | 116 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.h | 38 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_#linux | 3 android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.c | 514 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh | 20 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.h | 24 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl | 268 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/glob.tcl | 129 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup | 1 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt | 65 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch | 6 android/external/usb_modeswitch/usb_modeswitch/jim/auto.def | 436 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tree.tcl | 219 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an12.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl | 45 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh | 72 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.h | 48 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 | 5 android/external/usb_modeswitch/usb_modeswitch/jim/jim-file.c | 929 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-exec.c | 1619 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 | 172 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 | 4 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an12.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA | 4 android/external/usb_modeswitch/usb_modeswitch/jim/LICENSE | 45 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/make_string.tcl | 31 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl | 64 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 | 4 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an10.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE | 35 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a | 4 android/external/usb_modeswitch/usb_dongle/NetlinkHandler.cpp | 59 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f | 5 android/external/usb_modeswitch/usb_modeswitch/jim/configure.ac | 1 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 | 4 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an10.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms | 40 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-posix.c | 231 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 | 5 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ql-ril.conf | 42 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 | 6 android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an12.so | 0 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d | 2 android/external/usb_modeswitch/usb_dongle/Android.mk | 47 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 | 5 android/external/usb_modeswitch/usb_modeswitch/make_string.tcl | 31 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.h | 116 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c | 2095 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad | 4 android/external/usb_modeswitch/usb_modeswitch/dispatcher.c | 88 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-exec.c | 1619 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh | 17 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt | 88 android/external/usb_modeswitch/usb_modeswitch/jim/jim-pack.c | 380 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h | 87 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh | 72 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 | 2 android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c | 760 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 | 5 android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/dhcpcd | 0 android/external/usb_modeswitch/usb_modeswitch/jim/jim.h | 917 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 | 3 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh | 20 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff | 6 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service | 8 android/external/usb_modeswitch/usb_modeswitch/jim/glob.tcl | 129 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.cpp | 113 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/jim.c | 14478 ++++++ android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-load.c | 126 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 | 5 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 | 21 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b | 3 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb | 4 android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt | 85 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe | 4 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 | 4 android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl | 77 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 | 2 android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 | 6 1,188 files changed, 126,836 insertions(+), 18 deletions(-) diff --git a/android/device/softwinner/common/sepolicy/vendor/rild.te b/android/device/softwinner/common/sepolicy/vendor/rild.te index 8fdddc5..0dcdba2 100755 --- a/android/device/softwinner/common/sepolicy/vendor/rild.te +++ b/android/device/softwinner/common/sepolicy/vendor/rild.te @@ -8,3 +8,59 @@ allow rild vendor_toolbox_exec:file execute_no_trans; allow rild vendor_shell_exec:file execute_no_trans; + +# allow rild net_dns_prop:file { getattr open read }; +allow rild ppp_device:chr_file ioctl; +allow rild rootfs:dir { open read }; +#TODO removed for Q +#allow rild system_file:file execute_no_trans; +allow rild vendor_file:file execute_no_trans; +allow rild init:dir search; +allow rild init:file { open read }; +allow rild kernel:dir search; +allow rild kernel:file { open read }; +allow rild vendor_init:dir search; +allow rild vendor_init:file read; +allow rild vendor_toolbox_exec:file execute_no_trans; +allow rild hal_keymaster_default:dir search; +allow rild hwservicemanager:dir search; +allow rild logd:dir search; +allow rild servicemanager:dir search; +allow rild tee:dir search; +allow rild ueventd:dir search; +allow rild vendor_init:file open; +allow rild vndservicemanager:dir search; +allow rild hal_keymaster_default:file read; +allow rild hwservicemanager:file { open read }; +allow rild logd:file { open read }; +allow rild servicemanager:file { open read }; +allow rild tee:file read; +allow rild ueventd:file { open read }; +allow rild vndservicemanager:file read; +allow rild vold:dir search; +allow rild hal_audio_default:dir search; +allow rild hal_bluetooth_default:dir search; +allow rild hal_camera_default:dir search; +allow rild hal_keymaster_default:file open; +allow rild healthd:dir search; +allow rild tee:file open; +allow rild vndservicemanager:file open; +allow rild vold:file read; +allow rild hal_audio_default:file { open read }; +allow rild healthd:file { open read }; +allow rild vold:file open; +allow rild proc_net:file write; +allow rild self:packet_socket create; +allow rild self:packet_socket setopt; +allow rild self:packet_socket { bind read write read}; +allow rild audioserver:file { open read }; +allow rild hal_bluetooth_default:file { open read }; +allow rild hal_camera_default:file { open read }; +allow rild hal_cas_default:dir search; +allow rild hal_configstore_default:dir search; +allow rild hal_drm_clearkey:dir search; +allow rild hal_drm_default:dir search; +allow rild hal_drm_widevine:dir search; +allow rild lmkd:file { open read }; + + diff --git a/android/external/usb_modeswitch/CleanSpec.mk b/android/external/usb_modeswitch/CleanSpec.mk new file mode 100755 index 0000000..b0b9d8d --- /dev/null +++ b/android/external/usb_modeswitch/CleanSpec.mk @@ -0,0 +1,53 @@ +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/usb_modeswitch.d) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/usb_modeswitch) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/usb_dongle.rc) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/usb_dongle) diff --git a/android/external/usb_modeswitch/usb_dongle/Android.mk b/android/external/usb_modeswitch/usb_dongle/Android.mk new file mode 100755 index 0000000..f9fb9cf --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/Android.mk @@ -0,0 +1,47 @@ +LOCAL_PATH:= $(call my-dir) + +common_src_files := \ + NetlinkManager.cpp \ + NetlinkHandler.cpp \ + MiscManager.cpp \ + Misc.cpp \ + G3Dev.cpp + +common_shared_libraries := \ + libsysutils \ + libbinder \ + libcutils \ + liblog \ + libselinux \ + libutils \ + libbase \ + libhwbinder + +common_cflags := -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter + +#common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-* +common_local_tidy_checks := -*,clang-analyzer-security*,cert-*,-cert-err34-c,-cert-err58-cpp +common_local_tidy_checks += ,-cert-env33-c + +include $(CLEAR_VARS) + +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_MODULE := usb_dongle +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CLANG := true +LOCAL_TIDY := true +LOCAL_TIDY_FLAGS := $(common_local_tidy_flags) +LOCAL_TIDY_CHECKS := $(common_local_tidy_checks) +LOCAL_SRC_FILES := \ + main.cpp \ + $(common_src_files) + +LOCAL_INIT_RC := usb_dongle.rc + +LOCAL_CFLAGS := $(common_cflags) +#LOCAL_CFLAGS += -Werror=format +LOCAL_CFLAGS += -DUSE_USB_MODE_SWITCH + +LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) + +include $(BUILD_EXECUTABLE) diff --git a/android/external/usb_modeswitch/usb_dongle/G3Dev.cpp b/android/external/usb_modeswitch/usb_dongle/G3Dev.cpp new file mode 100755 index 0000000..55d928d --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/G3Dev.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/wait.h> +#include <sys/types.h> + + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> +#include <sysutils/NetlinkEvent.h> + +#include "G3Dev.h" +#include "MiscManager.h" +#include <unistd.h> + +#if PLATFORM_SDK_VERSION >= 16 +#define LOGV(fmt,args...) ALOGV(fmt,##args) +#define LOGD(fmt,args...) ALOGD(fmt,##args) +#define LOGI(fmt,args...) ALOGI(fmt,##args) +#define LOGW(fmt,args...) ALOGW(fmt,##args) +#define LOGE(fmt,args...) ALOGE(fmt,##args) +#endif + +static char modeswitch_cmd[256] = ""; + + +G3Dev::G3Dev(MiscManager *mm):Misc(mm) +{ + +} + +G3Dev::~G3Dev() { +} + +int G3Dev::handleUsbEvent(NetlinkEvent *evt) { + const char *devtype = evt->findParam("DEVTYPE"); + if( devtype!=NULL &&strcmp(devtype, "usb_device") ) + return 0; + pid_t status ; + + NetlinkEvent::Action action = evt->getAction(); + if( action == NetlinkEvent::Action::kAdd) + { + const char *product = evt->findParam("PRODUCT"); + if(product!=NULL && product[0] != 0 && devtype[0] != 0 ) + { + // ��ȡVID/PID + int vid = 0; + int pid = 0; + char * next = (char*)product; + vid = strtol(product, &next, 16); + + //char pre[]="sVe.GT"; + ++next; + pid = strtol(next, NULL, 16); + + SLOGD("== current usb device: %04X/%04X ===", vid, pid); + + char configure_file[2048]; + + + sprintf(configure_file, "/vendor/etc/usb_modeswitch.d/%04x_%04x", vid, pid); + if( access(configure_file, 0) == 0 ) + { + sprintf(modeswitch_cmd, "/vendor/bin/usb_modeswitch -W -v %04x -p %04x -c %s &", vid, pid,configure_file); + SLOGD("=== USB Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + } + } + } + + return 0; +} +int G3Dev::handleScsiEvent(NetlinkEvent *evt) { +/* + ��һ��������usb_device ���event��ִ�е�usb_modeswitchû�гɹ�����Ϊ���� + �ֶΣ���SCSI���event���ٴ�ִ��usb_modeswitch + */ + if(evt->getAction()==NetlinkEvent::Action::kAdd && modeswitch_cmd[0] != 0) + { + SLOGD("=== SCSI Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + modeswitch_cmd[0] = 0; + } + + return 0; +} +int G3Dev::handleUsb(){ + + + char configure_file[2048]; + int pid,vid; + this->get_tty_id(&vid,& pid); + + sprintf(configure_file, "/vendor/etc/usb_modeswitch.d/%04x_%04x", vid,pid); + SLOGD("=== config_file is: %04x_%04x", vid ,pid); + if( access(configure_file, 0) == 0 ) + { + sprintf(modeswitch_cmd, "/vendor/bin/usb_modeswitch -W -v %04x -p %04x -c %s &", vid, pid,configure_file); + SLOGD("=== USB Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + + } + return 0; + } +int G3Dev:: get_tty_id(int *vid, int* pid) +{ + + char linkto[1024]=""; + //SLOGD("began find device path"); + // SLOGD("device path: %s", tty_path);//// + + // LOGD("USB device path: %s", plink); + char pidpath[PATH_MAX]="/sys/bus/usb/devices/1-1"; + + FILE* fp = NULL; + char buf[5] = {0}; + strlcat(pidpath, "/idVendor",PATH_MAX); + SLOGD("Vendor path: %s", pidpath); + fp = fopen(pidpath, "r"); + if(fp == NULL) + return -2; + if(fread(buf, 1, 4, fp) != 4) + { + fclose(fp); + return -2; + } + fclose(fp); + *vid = atox(buf, 16); + char vidpath[PATH_MAX]="/sys/bus/usb/devices/1-1"; + //sys/bus/usb/devices/1-1 + strlcat(vidpath, "/idProduct",PATH_MAX); + // LOGD("Product path: %s", plink); + fp = fopen(vidpath, "r"); + if(fp == NULL) + return -3; + if(fread(buf, 1, 4, fp) != 4) + { + fclose(fp); + return -3; + } + fclose(fp); + *pid =atox(buf, 16); + + return 0; +} +#define EATCHAR(x, c) for (; *(x) == (c); (x)++) ; +/* -1:error. */ +int G3Dev:: atox( const char * line, int f_base ) +{ + int base = 10; + char max = '9'; + int v = 0; + + EATCHAR(line, ' '); + if(*line == 0) return 0; + + if( line[1] == 'x' || line[1] == 'X' ){ + base = 16; + max = 'f'; /* F*/ + line += 2; + } + else if(f_base==16) + { + base = 16; + max = 'f'; /* F*/ + } + + if( base == 10 ) { + while( *line >= '0' && *line <= max ) { + v *= base ; + v += *line-'0'; + line++; + } + } else { + while( *line >= '0' && *line <= max ) { + v *= base ; + if( *line >= 'a' ) + v += *line-'a'+10; + else if ( *line >= 'A' ) + v += *line-'A'+10; + else + v += *line-'0'; + line++; + } + } + return v; +} + diff --git a/android/external/usb_modeswitch/usb_dongle/G3Dev.h b/android/external/usb_modeswitch/usb_dongle/G3Dev.h new file mode 100755 index 0000000..2010dcb --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/G3Dev.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _G3DEV_H +#define _G3DEV_H + +#include <utils/List.h> + +#include "Misc.h" +class NetlinkEvent; + +class G3Dev : public Misc { +public: + G3Dev(MiscManager *mm); + virtual ~G3Dev(); + NetlinkEvent *env; + int handleUsbEvent(NetlinkEvent *evt); + int handleScsiEvent(NetlinkEvent *evt); + int handleUsb(); + int get_tty_id(int *vid, int* pid); + int atox( const char * line, int f_base ); +}; + +#endif + diff --git a/android/external/usb_modeswitch/usb_dongle/Misc.cpp b/android/external/usb_modeswitch/usb_dongle/Misc.cpp new file mode 100755 index 0000000..519201e --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/Misc.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> + +#include <cutils/properties.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include "Misc.h" + +Misc::Misc(MiscManager *mm) +{ + mMm = mm; + mDebug = false; +} + +Misc::~Misc() +{ +} + +void Misc::setDebug(bool enable) { + mDebug = enable; +} +/* + �ú�����������ʵ�� + */ +int Misc::handleUsbEvent(NetlinkEvent *evt) { + errno = ENOSYS; + return -1; +} + +/* + �ú�����������ʵ�� + */ +int Misc::handleScsiEvent(NetlinkEvent *evt) { + errno = ENOSYS; + return -1; +} + +int Misc::handleUsb() +{ errno = ENOSYS; + return -1;} + + diff --git a/android/external/usb_modeswitch/usb_dongle/Misc.h b/android/external/usb_modeswitch/usb_dongle/Misc.h new file mode 100755 index 0000000..e3d4f93 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/Misc.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MISC_H +#define _MISC_H + +#include <utils/List.h> + +class NetlinkEvent; +class MiscManager; + +class Misc { +protected: + MiscManager *mMm; + bool mDebug; + +public: + Misc(MiscManager *mm); + virtual ~Misc(); + + virtual int handleUsbEvent(NetlinkEvent *evt); + virtual int handleScsiEvent(NetlinkEvent *evt); + virtual int handleUsb(); + void setDebug(bool enable); +}; + +typedef android::List<Misc *> MiscCollection; + +#endif + diff --git a/android/external/usb_modeswitch/usb_dongle/MiscManager.cpp b/android/external/usb_modeswitch/usb_dongle/MiscManager.cpp new file mode 100755 index 0000000..06173e0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/MiscManager.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include <sysutils/NetlinkEvent.h> + +#include "MiscManager.h" + + +MiscManager *MiscManager::sInstance = NULL; + +MiscManager *MiscManager::Instance() { + if (!sInstance) + sInstance = new MiscManager(); + return sInstance; +} + +MiscManager::MiscManager() { + mDebug = false; + mMiscs = new MiscCollection(); + mBroadcaster = NULL; +} + +MiscManager::~MiscManager() { + delete mMiscs; +} + +void MiscManager::setDebug(bool enable) { + mDebug = enable; + MiscCollection::iterator it; + for (it = mMiscs->begin(); it != mMiscs->end(); ++it) { + (*it)->setDebug(enable); + } +} + +int MiscManager::start() { + return 0; +} + +int MiscManager::stop() { + return 0; +} + +int MiscManager::addMisc(Misc *m) { + mMiscs->push_back(m); + return 0; +} + +void MiscManager::handleEvent(NetlinkEvent *evt) { + const char *subsys = evt->getSubsystem(); + MiscCollection::iterator it; + bool hit = false; + + SLOGD("%s, %d", subsys, evt->getAction()); + + + for (it = mMiscs->begin(); it != mMiscs->end(); ++it) { + if (!strcmp(subsys, "usb")) { + (*it)->handleUsbEvent(evt); + } else if (!strcmp(subsys, "scsi_device")) { + (*it)->handleScsiEvent(evt); + } + } +} + diff --git a/android/external/usb_modeswitch/usb_dongle/MiscManager.h b/android/external/usb_modeswitch/usb_dongle/MiscManager.h new file mode 100755 index 0000000..a7cee2b --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/MiscManager.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MISCMANAGER_H +#define _MISCMANAGER_H + +#include <pthread.h> + +#include <utils/List.h> +#include <sysutils/SocketListener.h> +#include "Misc.h" + +class MiscManager { +private: + static MiscManager *sInstance; + +private: + SocketListener *mBroadcaster; + MiscCollection *mMiscs; + bool mDebug; + +public: + virtual ~MiscManager(); + + int start(); + int stop(); + + void handleEvent(NetlinkEvent *evt); + + int addMisc(Misc *v); + + void setDebug(bool enable); + + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } + SocketListener *getBroadcaster() { return mBroadcaster; } + + static MiscManager *Instance(); + +private: + MiscManager(); + Misc *lookupMisc(const char *label); +}; +#endif + diff --git a/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.cpp b/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.cpp new file mode 100755 index 0000000..32b5180 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include <sysutils/NetlinkEvent.h> +#include "NetlinkHandler.h" +#include "MiscManager.h" +NetlinkHandler::NetlinkHandler(int listenerSocket) : + NetlinkListener(listenerSocket) { +} + +NetlinkHandler::~NetlinkHandler() { +} + +int NetlinkHandler::start() { + return this->startListener(); +} + +int NetlinkHandler::stop() { + return this->stopListener(); +} + +void NetlinkHandler::onEvent(NetlinkEvent *evt) { + const char *subsys = evt->getSubsystem(); + + if (!subsys) { + SLOGW("No subsystem found in netlink event"); + return; + } + +#ifdef USE_USB_MODE_SWITCH + if (!strcmp(subsys, "usb") || !strcmp(subsys, "scsi_device")) { + SLOGW("subsystem found in netlink event"); + MiscManager *mm = MiscManager::Instance(); + mm->handleEvent(evt); +#endif + } +} diff --git a/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.h b/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.h new file mode 100755 index 0000000..56eb23c --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/NetlinkHandler.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NETLINKHANDLER_H +#define _NETLINKHANDLER_H + +#include <sysutils/NetlinkListener.h> + +class NetlinkHandler: public NetlinkListener { + +public: + explicit NetlinkHandler(int listenerSocket); + virtual ~NetlinkHandler(); + + int start(void); + int stop(void); + +protected: + virtual void onEvent(NetlinkEvent *evt); +}; +#endif diff --git a/android/external/usb_modeswitch/usb_dongle/NetlinkManager.cpp b/android/external/usb_modeswitch/usb_dongle/NetlinkManager.cpp new file mode 100755 index 0000000..63e7475 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/NetlinkManager.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/un.h> + +#include <linux/netlink.h> + +#define LOG_TAG "USB_DONGLE" + +#include <android-base/logging.h> + +#include "NetlinkManager.h" +#include "NetlinkHandler.h" + +NetlinkManager *NetlinkManager::sInstance = NULL; + +NetlinkManager *NetlinkManager::Instance() { + if (!sInstance) + sInstance = new NetlinkManager(); + return sInstance; +} + +NetlinkManager::NetlinkManager() { + mBroadcaster = NULL; +} + +NetlinkManager::~NetlinkManager() { +} + +int NetlinkManager::start() { + struct sockaddr_nl nladdr; + int sz = 64 * 1024; + int on = 1; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = getpid(); + nladdr.nl_groups = 0xffffffff; + + if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, + NETLINK_KOBJECT_UEVENT)) < 0) { + PLOG(ERROR) << "Unable to create uevent socket"; + return -1; + } + + // When running in a net/user namespace, SO_RCVBUFFORCE will fail because + // it will check for the CAP_NET_ADMIN capability in the root namespace. + // Try using SO_RCVBUF if that fails. + if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) && + (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) { + PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option"; + goto out; + } + + if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { + PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option"; + goto out; + } + + if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { + PLOG(ERROR) << "Unable to bind uevent socket"; + goto out; + } + + mHandler = new NetlinkHandler(mSock); + if (mHandler->start()) { + PLOG(ERROR) << "Unable to start NetlinkHandler"; + goto out; + } + + return 0; + +out: + close(mSock); + return -1; +} + +int NetlinkManager::stop() { + int status = 0; + + if (mHandler->stop()) { + PLOG(ERROR) << "Unable to stop NetlinkHandler"; + status = -1; + } + delete mHandler; + mHandler = NULL; + + close(mSock); + mSock = -1; + + return status; +} diff --git a/android/external/usb_modeswitch/usb_dongle/NetlinkManager.h b/android/external/usb_modeswitch/usb_dongle/NetlinkManager.h new file mode 100755 index 0000000..9c7ba11 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/NetlinkManager.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NETLINKMANAGER_H +#define _NETLINKMANAGER_H + +#include <sysutils/SocketListener.h> +#include <sysutils/NetlinkListener.h> + +class NetlinkHandler; + +class NetlinkManager { +private: + static NetlinkManager *sInstance; + +private: + SocketListener *mBroadcaster; + NetlinkHandler *mHandler; + int mSock; + +public: + virtual ~NetlinkManager(); + + int start(); + int stop(); + + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } + SocketListener *getBroadcaster() { return mBroadcaster; } + + static NetlinkManager *Instance(); + +private: + NetlinkManager(); +}; +#endif diff --git a/android/external/usb_modeswitch/usb_dongle/main.cpp b/android/external/usb_modeswitch/usb_dongle/main.cpp new file mode 100755 index 0000000..1e29146 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/main.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NetlinkManager.h" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <cutils/klog.h> +#include <cutils/properties.h> +#include <cutils/sockets.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <getopt.h> +#include <fcntl.h> +#include <dirent.h> + +#ifdef USE_USB_MODE_SWITCH +#include "G3Dev.h" +#include "MiscManager.h" +#endif + +#define LOG_TAG "USB_DONGLE" + +static void coldboot(const char *path); + +struct fstab *fstab; + +struct selabel_handle *sehandle; + +using android::base::StringPrintf; + +int main(int argc, char** argv) { + setenv("ANDROID_LOG_TAGS", "*:v", 1); + android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + + LOG(INFO) << "USB_MODE_SWITCH"; + + NetlinkManager *nm; + + + klog_set_level(6); + + if (!(nm = NetlinkManager::Instance())) { + LOG(ERROR) << "Unable to create NetlinkManager"; + exit(1); + } + + if (nm->start()) { + PLOG(ERROR) << "Unable to start NetlinkManager"; + exit(1); + } + +#ifdef USE_USB_MODE_SWITCH + MiscManager *mm; + if (!(mm = MiscManager::Instance())) { + PLOG(ERROR) << "Unable to create MiscManager"; + exit(1); + }; + //mm->setBroadcaster((SocketListener *) cl); + if (mm->start()) { + LOG(ERROR) << "Unable to start MiscManager"; + exit(1); + } + G3Dev* g3 = new G3Dev(mm); + g3->handleUsb(); + mm->addMisc(g3); +#endif + // Do coldboot here so it won't block booting, + // also the cold boot is needed in case we have flash drive + coldboot("/sys/block"); + // Eventually we'll become the monitoring thread + while(1) { + pause(); + } + + LOG(ERROR) << "USB_MODE_SWITCH exiting"; + exit(0); +} + +static void do_coldboot(DIR *d, int lvl) { + struct dirent *de; + int dfd, fd; + + dfd = dirfd(d); + + fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC); + if(fd >= 0) { + write(fd, "add\n", 4); + close(fd); + } + + while((de = readdir(d))) { + DIR *d2; + + if (de->d_name[0] == '.') + continue; + + if (de->d_type != DT_DIR && lvl > 0) + continue; + + fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if(fd < 0) + continue; + + d2 = fdopendir(fd); + if(d2 == 0) + close(fd); + else { + do_coldboot(d2, lvl + 1); + closedir(d2); + } + } +} + +static void coldboot(const char *path) { + DIR *d = opendir(path); + if(d) { + do_coldboot(d, 0); + closedir(d); + } +} diff --git a/android/external/usb_modeswitch/usb_dongle/usb_dongle.rc b/android/external/usb_modeswitch/usb_dongle/usb_dongle.rc new file mode 100755 index 0000000..c20f161 --- /dev/null +++ b/android/external/usb_modeswitch/usb_dongle/usb_dongle.rc @@ -0,0 +1,4 @@ +service usb_dongle /vendor/bin/usb_dongle + class main + oneshot + diff --git a/android/external/usb_modeswitch/usb_modeswitch/Android.mk b/android/external/usb_modeswitch/usb_modeswitch/Android.mk new file mode 100755 index 0000000..5dacae0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +INCLUDES = $(LOCAL_PATH) +INCLUDES += external/libusb/libusb + +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE := usb_modeswitch +LOCAL_SRC_FILES := usb_modeswitch.c +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES :=$(INCLUDES) +LOCAL_SHARED_LIBRARIES := libusb + +LOCAL_CFLAGS += -Wno-self-assign -Wno-sometimes-uninitialized +LOCAL_CFLAGS += -Wno-error=deprecated-declarations -Wno-deprecated-declarations + +$(shell mkdir -p $(PRODUCT_OUT)/vendor/etc) +$(shell cp -R $(LOCAL_PATH)/usb_modeswitch.d $(PRODUCT_OUT)/vendor/etc) + +include $(BUILD_EXECUTABLE) + diff --git a/android/external/usb_modeswitch/usb_modeswitch/COPYING b/android/external/usb_modeswitch/usb_modeswitch/COPYING new file mode 100755 index 0000000..d60c31a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/android/external/usb_modeswitch/usb_modeswitch/ChangeLog b/android/external/usb_modeswitch/usb_modeswitch/ChangeLog new file mode 100755 index 0000000..42ee92a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/ChangeLog @@ -0,0 +1,288 @@ + +History of USB_ModeSwitch +========================= + +Version 2.4.0, 2016/06/12 + ATTENTION: All ad-hoc driver binding code (using new_id driver attribute) + removed - was a potential source of side effects and should now be + obsoleted by good kernel support for modems; Added "dummy" setting for + config files, to conditionally refrain from handling a device (see this + topic: www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?f=4&t=2458 ); + extended StandardEject sequence to include LUN 1, required for some D-Link + devices; add device class 239 ("miscellaneous") to sanity check (thanks to + Daniel Drake for reporting); udev shell script - removed driver binding, + removed almost all waiting and forking, improved check for systemd (thanks + to Daniel Drake for problem analysis and solution, see this topic/patch: + www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?p=16777#p16777 , + gist.github.com/dsd/9f83c4830ab78ce94078aedb2cf16a8f ) +Version 2.3.0, 2016/01/12 + ATTENTION: -I flag is now history and being ignored - determining SCSI + attributes is really an 'outside task'; -n flag (NeedResponse) is being + ignored, CSW response will now always be read; introduction of parameter + "OptionMode", wrapping the standard bulk message for all newer Huawei + devices; fixed missing variable initialization in dispatcher script which + could lead to crash (thanks, Dmitry Kunilov!); fixed bug which prevented + early logging; fixed success report for Cisco AM10; some source code + formatting and clean-up +Version 2.2.6, 2015/11/01 + Renamed function abort(), avoiding possible conflicts in static builds + with libjim (thanks, Gustavo Zacharias); removed storage class check of + interface 0 from dispatcher, enabling new multi-config devices in data + package 20151101 +Version 2.2.5, 2015/07/16 + Fixed bug in configuration check, possibly leading to segfault (thanks, + Leonid Lisovskiy); fixed Pantech commandline parameter evaluation (was + not working at all); added driver unbind step via sysfs in wrapper, + getting rid of the USB subsystem complaint "interface 0 claimed by + usb-storage while 'usb_modeswitch' <does this and that>" +Version 2.2.4, 2015/07/14 + Fixed buggy check of USB configuration selection (possibly leading + to segfault), tested with Alcatel X602D; removed call to 'libusb_strerror' + from libusb initialization - not available in earlier libusb1 versions +Version 2.2.3, 2015/06/29 + Fixed problem arising with systemd version 221 (220 untested), which + affects starting the usb_modeswitch systemd unit from the sh script + (reported by Archlinux users) +Version 2.2.2, 2015/06/27 + Added catch for libusb init error (thanks, Henrik Gustafsson); removed + global function result variable; added catch for USB configuration + read error (both thanks to "otila"); fixed wrapper script where port + search for symlinking modem port was broken ("/dev/gsmmodem"); changed + PantechMode parameter to represent different targets; added global + config option to disable MBIM checking and setting alltogether (request + from "kai"); changed udev sh script so that systemd processing takes + precedence over upstart; changed systemd template unit parameter to + avoid escaping problems +Version 2.2.1, 2015/01/15 + Fixed unreliable switching function for Cisco AM10 +Version 2.2.0, 2014/05/29 + Introduction of parameter "HuaweiNewMode", wrapping the standard bulk + message for all newer Huawei devices; support for generic fall-back + config files, combined with OS switch (per vendor ID), implementation + to use a specific switching command on Android for all Huawei devices + (see README of data package for details); this change was suggested + by Huawei +Version 2.1.1, 2014/03/27 + Code cleanup, better use of libusb1; this also fixes problems with + determination of the active USB configuration (Samsung, Option modems); + "Interface" parameter was not working as expected, fixed (see also: + https://bugs.launchpad.net/bugs/1261923 ); fixed bogus interface release + in "inquire" function, again a report by "Sonya@zte" +Version 2.1.0, 2014/01/28 + ATTENTION: -I flag meaning reversed, default is to skip SCSI inquiry; + introduction of StandardEject, replacing many MessageContents with the + same function, reducing size of device config files, and always including + the 'Allow Medium Removal' before ejecting (thanks to Lars Melin for + the idea); fix in "bulk_read", removing bogus CSW request (report from + "Sonya@zte") +Version 2.0.1, 2013/09/03 + Fixed stupid string size bug which could lead to memory corruption + (thanks to Leonid Myravjev) +Version 2.0.0, 2013/09/01 + Switched to libusb1.0, with much help from folks of the wl500g project + (http://wl500g.googlecode.com): Vladislav Grishenko, Leonid Lisovskiy, + Roman Samarev, Andrey Tikhomirov; + major code and debug output cleanup; man page corrections and additions + (thanks to Thomas Haller); + experimental systemd and upstart integration, if present + (Explanation: newer udev versions kill all subprocesses, detached or + not. The suggested way to handle longer running processes like the + usb_modeswitch_dispatcher is to add simple services or tasks and start + these by sending signals from the udev rule) + !! Attention, system integrators: a crude install facility is included + in the Makefile to check if "upstart" or "systemd" is active and to + install the matching service file; you may want to adapt it better to + your respective system, possibly adding dependencies/targets to the + services. Note that the udev starter script usb_modeswitch.sh also + checks for the existence of the service/unit files +Version 1.2.7, 2013/08/07 + Two new dedicated control message functions to support Pantech LTE + (thanks to Adam Goode) and Blackberry Q10/Z10 (thanks to Daniel Mende) +Version 1.2.6, 2013/06/02 + Several changes to streamline compiling as part of larger projects + (thanks to Nicolas Carrier), mostly in Makefile; fix compiler warnings + appearing in certain build environments (N. Carrier); new Quanta + procedure (thanks to Andrey Tikhomirov) for Quanta 1K3 LTE; fix for + error with cascaded hubs in dispatcher script (hint from N. Carrier) +Version 1.2.5, 2012/11/09 + Initial support for MBIM devices, use with data package >= 20121109; + checking for these is the automatic default, new parameter NoMBIMCheck + prevents the check per device in case of problems; new global option + to set "delay_use" of usb-storage (as low values may prevent + mode-switching); fix for handling multi-configuration devices (thanks + to Bjørn Mork for advice) +Version 1.2.4, 2012/08/12 + Additional interface checks to prevent sending UFI commands to non- + storage interfaces (prompted by more ambiguous device IDs popping up); + change in SierraMode for handling newer devices which caused an error + abort before; Makefile fix for parallelized make runs +Version 1.2.3, 2012/01/28 + Fixed two bugs both causing the embedded-jimsh install variant of the + dispatcher crash (the "pure-script" install variant was NOT affected); + fixed some "regexp" incompatibilities with Debian's libjim +Version 1.2.2, 2012/01/19 + Fixed bad bug preventing mode switch for devices using TargetClass; + improved logging in case of negative success check +Version 1.2.1, 2011/12/26 + Fixed possible ambiguities when multiple identical modems are plugged + synchronously; this is achieved by adding -b and -g parameter (busnum + and devnum) for proper id'ing; some resulting workflow changes and + shortcuts in "system integration" mode (use sysfs/wrapper for success + control, reduce informative checks); improved hub usage robustness; + future data packages can be ridded of redundancies (default ID, success + check parameters), resulting in smaller files; + fixed bad bug which may prevent switching completely when logging is + not activated; fixed possible overflow in dispatcher C code (thanks to + Gilles Espinasse) +Version 1.2.0, 2011/10/23 + Added QisdaMode for Qisda H21 (thanks to Chi-Hang Long for the code); + dispatcher can now be installed with an embedded interpreter, so that + Tcl is no longer required; added command line options for binary program + to accept configuration data via stdin or as a long string parameter - + this fixes the bug with non-writable temporary file during boot; + reversed skipping of pre-switching delay, which has caused problems; + fixed potential buffer overflow (thanks to Rafael Silva for the find); + get first interface right even on some broken devices (thanks to + Alexander Gordeev for the patch); increased post-switch delay before + driver binding to avoid possible conflict with usb-storage +Version 1.1.9, 2011/08/05 + Added CiscoMode for Valet device; additional checking for CDC ACM device + to prevent erroneous driver loading after switching; no more post-switch + check for access to initial device if target parameters are given +Version 1.1.8, 2011/06/19 + Cleaned up switchSendMessage(); added workaround for quirky devices not + reporting configuration setting; added non-CSW response for arbitrary + bulk transfers; added SequansMode and MobileActionMode; check for active + configuration will be skipped if bNumConfigurations is 1 (most cases) +Version 1.1.7, 2011/02/27 + Attention: paths for runtime files and database have changed! Old places + will be found but are deprecated; /usr/share/usb_modeswitch for database, + /var/lib/usb_modeswitch for "remembered" IDs; + fix for configuration setting race (thanks to Amit Mendapara); discovered + incompatibility between Tcl versions <= 8.3 and >=8.4, so 8.4 is the + minimum prerequisite now; + first availability of an alternative source pack which includes "jimsh", + a fast Tcl mini shell, intended for resource-constrained systems +Version 1.1.6, 2010/12/22 + Moved warm-boot driver binding to sh wrapper, was unreliable in 1.1.5; + sh wrapper overhaul, made compatible with Ubuntu's "dash" shell, tclsh + calls reduced further; initial device checking includes current + bConfigurationValue now, should work with config setting for multiple + devices; made tcl script conform to limitations of "jimsh", the minimal + tcl shell (hint from Barry Kauler); fixes for "usbserial" fallback + (driver binding for old systems); in the C program, changed parameter + "MessageDelay" (hitherto unused) to "ReleaseDelay", to be used in one + device configuration (delay interface release after bulk message sending) +Version 1.1.5, 2010/11/28 + Added special control message for Kobil devices (patch from Filip Aben); + try to get active configuration for interface class checking (there are + some new devices 'switching' via configuration selection); + fixed "0000" target product ID - again; new bash and tcl wrapper logic: + the convenience functions for driver binding and symlinking will now + start the tcl shell ONLY for known devices; changed and appended logging + capabilities of said convenience functions; add loading of "usbserial" + as a fallback for older systems to support new devices; + add workaround for bug in libusb1 which affects device search during + success check +Version 1.1.4, 2010/08/17 + The package should work at boot time now (cold and warm); + product IDs of "0000" do exist but were not accepted, fixed (thanks to + Sakis Dimopoulos); response endpoint is now always detected (led to + possible error report when resetting all endpoints in version 1.1.3); + wrapper script can now work with a packed collection of config files as + well as with the plain folder of files; use with the "install-packed" + make target of the data package (for use on systems with resource + constraints); wrapper fix for the symlink feature: handling of multiple + interrupt ports was incomplete; wrapper does not longer use a temporary + file for the symlink feature (security considerations, Marco d'Itri) +Version 1.1.3, 2010/06/21 + Added delay option to separate multiple message transfers by millisecs; + fixed (possibly dangerous) sloppy string handling (thanks to Christophe + Fergeau); added "clear_halt" for response endpoint; small additions in + Makefile (install with -D); changes in option handling (NO MORE DEFAULT + CONFIG FILE!) and help text; symlink feature in wrapper can now cope + with devices providing more than one interrupt port; wrapper now ignores + package manager leftovers in config folder; replaced bash-specific syntax + in wrapper; changed ZTE skipping (if existing rules are found) to warning +Version 1.1.2, 2010/04/18 + Added support for two additional bulk messages; wrapper handles special + ZTE case; generalized driver loading, new parameter "DriverModule" and + "DriverIDPath"; new wrapper facility to add symlink pointing to interrupt + port (used in rule file from data pack >= 20100418) +Version 1.1.1, 2010/03/17 + Attention: old usb_modeswitch.conf renamed to usb_modeswitch.setup! + Add separate config file for wrapper (global settings for switching and + logging); add config file option to disable driver loading; handling of + kernel attribute AVOID_RESET_QUIRK added; bug fixed in SonyMode (reported + by "no-0n3"); bug fixed in SuccessCheck logic; minor flow alignments and + fixes; new devices +Version 1.1.0, 2010/01/24 + Attention: wrapper script location changed, uninstall old versions! + Major fixes in the wrapper script (stabilizing and time-saving); + back to unified installation, defaults to "integrated" approach; + new -D parameter to enable "integrated" behaviour; bugs fixed in + success check; man file included (borrowed from the Debian package); + C code and binary works with the compat library from libusb-1.0; + some new devices +Version 1.0.7, 2010/01/06 + Bug fixed for Sony mode, thanks to Marco Chiaranda; fix for parameter + substitution in newer udev versions, fix for bad bug in wrapper script + practically disabling automatic mode +Version 1.0.6, 2009/12/21 + New "GCT Mode", fixes for device quirks (NXP Dragonfly), fix for multiple + Huawei devices, cleanups, loads of new devices in config file and database, + minor tcl script changes +Version 1.0.5, 2009/08/26 + More changes and fixes regarding success check; "--version" option; + config "database" updated +Version 1.0.4, 2009/08/23 + Success check bugs (and others) fixed +Version 1.0.3, 2009/08/20 + Success check improved; experimental system integration (fully automated), + optional; new parameter "TargetProductList" needed for this; other + necessary small adaptations; more devices +Version 1.0.2, 2009/06/10 + Output bugs fixed +Version 1.0.1, 2009/06/08 + Added output of descriptor strings for further identification +Version 1.0.0, 2009/06/01 + Attention: possible incompatibilities for command line control! + On/off flags don't require arguments anymore (-H, -S, -O, -d, -R, + -n, new: -I), meaning "-R 0" does a reset like "-R 1" or "-R"; + long option names changed to standard format (e.g. --HuaweiMode to + --huawei-mode); added device inquiry, for future help with device + identification; catch error -19 as possible success; send and response + endpoints now autoselected (consequently NeedResponse is back); + new devices +Version 0.9.7, 2009/04/15 + Updated SonyMode, MD 400 now stable; automatic default endpoint + detection from Andrew Bird +Version 0.9.7beta, 2009/03/15 + Major code clean up, optional success control (both suggested + by Daniel Cooper), new devices +Version 0.9.6, 2009/01/08 + Special modes added for Sierra and Sony Ericsson, new devices +Version 0.9.5, 2008/10/27 + New options for USB tuning (jokedst), lots of new devices, clean up +Version 0.9.4, 2008/06/09 + Compat fix for libusb on FreeBSD quirks, more devices +Version 0.9.4beta2, 2008/03/19 + Successful udev device release fix +Version 0.9.4beta, 2008/03/16 + Multiple device support +Version 0.9.3, 2008/03/09 + More devices, no changes from beta version +Version 0.9.3beta, 2007/12/30 + New TargetClass parameter for recent Option firmware (Paul Hardwick), more + devices +Version 0.9.2, 2007/11/02 + New Huawei mode (code from Miroslav Bobovsky, added by Denis Sutter), more + devices +Version 0.9.1beta, 2007/09/04 (jokedst) + Added command line parsing, cleaned up config stuff, doc updates +Version 0.9beta, 2007/08/15 + Name change from "icon_switch", parameter file and generalizing +Version 0.2, 2006/09/25 + Code cleaning, more messages +Version 0.1, 2006/09/24 + (as "icon_switch") Just very basic functionality ... diff --git a/android/external/usb_modeswitch/usb_modeswitch/CleanSpec.mk b/android/external/usb_modeswitch/usb_modeswitch/CleanSpec.mk new file mode 100755 index 0000000..b0b9d8d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/CleanSpec.mk @@ -0,0 +1,53 @@ +# Copyright (C) 2007 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/usb_modeswitch.d) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/usb_modeswitch) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/usb_dongle.rc) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/usb_dongle) diff --git a/android/external/usb_modeswitch/usb_modeswitch/Makefile b/android/external/usb_modeswitch/usb_modeswitch/Makefile new file mode 100755 index 0000000..47ed794 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/Makefile @@ -0,0 +1,105 @@ +PROG = usb_modeswitch +VERS = 2.4.0 +CC ?= gcc +CFLAGS += -Wall +LIBS = `pkg-config --libs --cflags libusb-1.0` +RM = /bin/rm -f +OBJS = usb_modeswitch.c +PREFIX = $(DESTDIR)/usr +ETCDIR = $(DESTDIR)/etc +SYSDIR = $(ETCDIR)/systemd/system +UPSDIR = $(ETCDIR)/init +UDEVDIR = $(DESTDIR)/lib/udev +SBINDIR = $(PREFIX)/sbin +MANDIR = $(PREFIX)/share/man/man1 +VPATH = jimtcl +HOST_TCL := $(shell cd jim && ./autosetup/find-tclsh) +ifeq (,$(findstring jimsh0,$(HOST_TCL))) +TCL ?= $(HOST_TCL) +else +TCL ?= /usr/bin/tclsh +endif +JIM_CONFIGURE_OPTS = --disable-lineedit \ + --with-out-jim-ext="stdlib posix load signal syslog" --prefix=/usr + +.PHONY: clean install install-common uninstall \ + script shared static \ + dispatcher-script dispatcher-shared dispatcher-static \ + install-script install-shared install-static + +all: script + +script: $(PROG) dispatcher-script + +shared: $(PROG) dispatcher-shared + +static: $(PROG) dispatcher-static + +$(PROG): $(OBJS) usb_modeswitch.h + $(CC) -o $(PROG) $(OBJS) $(CFLAGS) $(LIBS) $(LDFLAGS) + +jim/libjim.so: + cd jim && CFLAGS="$(CFLAGS)" CC="$(CC)" ./configure $(JIM_CONFIGURE_OPTS) --shared + $(MAKE) -C jim lib + +jim/libjim.a: + cd jim && CFLAGS="$(CFLAGS)" CC="$(CC)" ./configure $(JIM_CONFIGURE_OPTS) + $(MAKE) -C jim lib + +dispatcher-script: usb_modeswitch.tcl + sed 's_!/usr/bin/tclsh_!'"$(TCL)"'_' < usb_modeswitch.tcl > usb_modeswitch_dispatcher + +dispatcher-shared: jim/libjim.so dispatcher.c usb_modeswitch.string + $(CC) dispatcher.c $(LDFLAGS) -Ljim -ljim -Ijim -o usb_modeswitch_dispatcher $(CFLAGS) + +dispatcher-static: jim/libjim.a dispatcher.c usb_modeswitch.string + $(CC) dispatcher.c $(LDFLAGS) jim/libjim.a -Ijim -o usb_modeswitch_dispatcher $(CFLAGS) + +usb_modeswitch.string: usb_modeswitch.tcl + $(HOST_TCL) make_string.tcl usb_modeswitch.tcl > $@ + +clean: + $(RM) usb_modeswitch + $(RM) usb_modeswitch_dispatcher + $(RM) usb_modeswitch.string + $(RM) jim/autosetup/jimsh0 + $(RM) jim/autosetup/jimsh0.c + +distclean: clean + -$(MAKE) -C jim distclean + +ums-clean: + $(RM) usb_modeswitch + $(RM) usb_modeswitch_dispatcher + $(RM) usb_modeswitch.string + +# If the systemd folder is present, install the service for starting the dispatcher +# If not, use the dispatcher directly from the udev rule as in previous versions + +install-common: $(PROG) usb_modeswitch_dispatcher + install -D --mode=755 usb_modeswitch $(SBINDIR)/usb_modeswitch + install -D --mode=755 usb_modeswitch.sh $(UDEVDIR)/usb_modeswitch + install -D --mode=644 usb_modeswitch.conf $(ETCDIR)/usb_modeswitch.conf + install -D --mode=644 usb_modeswitch.1 $(MANDIR)/usb_modeswitch.1 + install -D --mode=644 usb_modeswitch_dispatcher.1 $(MANDIR)/usb_modeswitch_dispatcher.1 + install -D --mode=755 usb_modeswitch_dispatcher $(SBINDIR)/usb_modeswitch_dispatcher + install -d $(DESTDIR)/var/lib/usb_modeswitch + test -d $(UPSDIR) -a -e /sbin/initctl && install --mode=644 usb-modeswitch-upstart.conf $(UPSDIR) || test 1 + test -d $(SYSDIR) -a \( -e /usr/bin/systemctl -o -e /bin/systemctl \) && install --mode=644 usb_modeswitch@.service $(SYSDIR) || test 1 + +install: install-script + +install-script: dispatcher-script install-common + +install-shared: dispatcher-shared install-common + +install-static: dispatcher-static install-common + +uninstall: + $(RM) $(SBINDIR)/usb_modeswitch + $(RM) $(SBINDIR)/usb_modeswitch_dispatcher + $(RM) $(UDEVDIR)/usb_modeswitch + $(RM) $(ETCDIR)/usb_modeswitch.conf + $(RM) $(MANDIR)/usb_modeswitch.1 + $(RM) -R $(DESTDIR)/var/lib/usb_modeswitch + $(RM) $(SYSDIR)/usb_modeswitch@.service diff --git a/android/external/usb_modeswitch/usb_modeswitch/README b/android/external/usb_modeswitch/usb_modeswitch/README new file mode 100755 index 0000000..da6fb351 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/README @@ -0,0 +1,271 @@ +README for USB_ModeSwitch + +For up-to-date and more detailed information (plus a friendly forum) visit +http://www.draisberghof.de/usb_modeswitch + + +What it is +========== + +USB_ModeSwitch is - hardly surprising - a mode switching tool for controlling +USB devices with multiple "modes". Now, what does THAT mean? + +More and more USB devices have their MS Windows drivers onboard; when plugged +in for the first time they act like a flash storage and offer their driver +installation from there. +After installation (and on every consecutive plugging) the driver switches the +mode internally by sending a certain command sequence; the storage device +vanishes (in most cases) and a different device - like a USB modem - shows up. +To the host, this is like unplugging one device and then plugging annother. + +At first this feature appeared on devices with cell phone chipsets, presumably +because some of them were already able to change the mode of their USB port +from storage to communication - so why not make use of this in a modem stick? +Modem maker "Option" calls that feature "ZeroCD (TM)" since it eliminates the +need for shipping a separate driver carrier. + +In the beginning, nothing of this was documented in any form and there was +hardly any Linux/Unix support available. +On the good side, most of the known devices are working out of the box in all +modes with available Linux modules like "usb-storage" or serial USB drivers. +That leaves only the problem of the mode-switching from storage to whatever +the thing is supposed to do. + +Fortunately there are things like human smartness, USB sniffing programs and +LibUSB. The obvious way is to eavesdrop on the communication of the MS Windows +driver, to isolate the command or action that does the switching, and then re- +play the same sequence in a non-Windows system. + +In theory, this task could also be handled on the kernel driver level, but a +userspace program is much more flexible and can easily be disabled if access +to the initial mode of those devices should be desired. There has been a +principle decision by kernel developers to keep mode-switching outside of the +kernel. + +So USB_ModeSwitch has evolved to make this process easy to handle by taking the +relevant parameters from configuration files and handling all initialization +and communication business, with essential help from "libusb". + +In Linux and friends it is intended to work automatically - via udev events +and rules - and doing the mode switch without any user interaction. +However, the core C program should be as portable als libusb itself; it does not +rely on specific Linux features. +It can also be run as an interactive command line tool, particularly useful when +trying to tinker with hitherto unknown devices. + +We have already collected a wide range of information on how to mode-switch all +sorts of devices. If you run into a new one that is unknown yet, don't despair: +we can find out what you need to do! + + +How to install +============== + +If you only need the core C program, just run "make". All further steps de- +scribed below are referring to a common, fairly current Linux system where +USB_ModeSwitch is expected to do its work automatically. + +!! You need the usb-modeswitch-data package from the same source as this !! + +If you have an earlier version installed, de-installation is recommended ("make +uninstall") but not mandatory. The wrapper script location changed in 1.1.0; +old files might be orphaned but will not do any harm. + +The main prerequisite for installing from source is the development package for +"libusb". It may be called "libusb-dev" or similar in your distribution. From +usb_modeswitch 2.0.0 on, it should have an "1.x" in the name to reflect the change +to libusb-1. There are also variants around called "libusbx" if libusb-1 is not +available on your distribution. + +To install the tool set, unpack and run the install command (see below) in the +newly created directory. + +From version 1.2.0, there are three flavours of installing. The only difference +between those is the way the dispatcher is installed, but this affects the +dependencies as well: + +1. If you have the "Tcl" scripting language available on your system (packages + "tcl" or "jimsh"), use the light-weight installation: + + # make install + +2. If you are size-constrained and have the Jimsh library on your system + (package "libjim-dev"), you can have the Tcl interpreter embedded with the + dispatcher, using its shared lib: + + # make install-shared + +3. If you are size-constrained and definitely don't need a Tcl interpreter + for anything else, choose the statically embedded flavour. This will have + no further dependency as it uses the included interpreter code, which is + configured for small size: + + # make install-static + +Note that the "static"/"shared" targets are NOT referring to the usb_modeswitch +program, only to the dispatcher! +Any one of these commands will install a small posix shell script, the +dispatcher (wrapper) as script or as binary, a global config file, the core +program and a man page. + +Install the data package as well and you are set. + +NOTE: installing over (possibly outdated) Linux distribution packages of this +program and the data collection should not be a problem. + + +How to use +========== + +If your device is known, you should be able to just plug it and use it. If +it doesn't work - we will find out why. + +For manual use just run "usb_modeswitch" (as root). Work with the command +line interface or with a setup file. You can use any file and give its path +with the "-c" parameter. +The file named "device_reference.txt" that you can find on the home site of +this package is a device and configuration reference containing most known +devices; you can use it as a "database" to create your own configuration file. +It's heavily commented and should tell you what to do. It also contains a +thorough explanation of all the parameters. + +Run "usb_modeswitch -h" to list the command line parameters. +See also the provided man page. + +Important note: Manual use is mainly intended for testing and analyzing!! +The program puts no limits on what you can send to your USB device, so I +assume it is possible to screw it up profoundly. + +Once your new device is switching fine you can add it to the data files to +make the process automatic. + +For this to work, add a rule entry to the rules file to let udev run +usb_modeswitch as soon as the default IDs are found (when the device is +plugged). If you look into the rules file you will see immediately how +your new entry should look like. +The location is: +/lib/udev/rules.d/40-usb_modeswitch.rules + +Then add your new config file to the folder +"/etc/usb_modeswitch.d" (only for custom config files!). +And don't forget to report your success !! + +Again, remember that the rules file and the default device config folder +(/usr/share/usb_modeswitch) are installed by the usb_modeswitch data package. + + +########## +Important: libusb programs - like this tool - want to be run with administrative +privileges (as root or with sudo)! +########## + + + +Known working hardware, Troubleshooting +======================================= + +Please go to the homepage (see link at the top). Read carefully. +For support questions use ONLY public posts in the forum. + + + +Contribute +========== + +USB_ModeSwitch comes quite handy for experimenting with your own hardware if +not supported yet. You could try this approach: + +Note the device's vendor and product ID from /proc/bus/usb/devices (or from the +output of lsusb); the assigned driver is usually "usb-storage". Then try spying +on the USB communication to the device with the same ID inside MS Windoze. I +recommend this tool: +"SniffUSB" (http://benoit.papillault.free.fr/usbsnoop/index.php.en). + +PLEASE post any improvements, new device information and/or bug reports to the +forum (see above) or send it to the author (see below)! + + +Whodunit +======== + +Copyright 2007 - 2015 Josua Dietze (for non-support notifications write a personal +message through the forum to "Josh"; everything else only in a forum thread) + + !!! NO SUPPORT QUESTIONS VIA E-MAIL, use the forum !!! + +Major contributions: + +Command line parsing and other essential contributions: + Joakim Wennergren + +TargetClass parameter implementation to support new Option devices/firmware: + Paul Hardwick (http://www.pharscape.org) + +Created with initial help from: + "usbsnoop2libusb.pl" by Timo Lindfors + (http://iki.fi/lindi/usb/usbsnoop2libusb.pl) + +Config file parsing code borrowed from: + Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html) + +Hexstr2bin function borrowed from: + Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c") + +Indispensable help with device research and compilation: + Lars Melin + +Code, fixes and ideas contributed by: + Aki Makkonen + Denis Sutter + Lucas Benedicic + Roman Laube + Luigi Iotti + Vincent Teoh + Tommy Cheng + Daniel Cooper + Andrew Bird + Yaroslav Levandovskiy + Sakis Dimopoulos + Steven Fernandez + Christophe Fergeau + Nils Radtke + Filip Aben + Amit Mendapara + Roman S. Samarev + Chi-Hang Long + Andrey Tikhomirov + Daniel Mende + Nicholas Carrier + Adam Goode + Leonid Lisovskiy + Vladislav Grishenko + Daniel Drake + +Device information contributors are named in the "device_reference.txt" file. + +JimTcl is currently maintained by Steve Bennett; see README in subfolder + for details. It is released under a FreeBSD-style license. + Visit http://jim.tcl.tk/ + + + +Legal +===== + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details: + +http://www.gnu.org/licenses/gpl.txt + +Or find it as the file COPYING in this folder. + + + + +Last revised: 2016-06-12, Josua Dietze diff --git a/android/external/usb_modeswitch/usb_modeswitch/dispatcher.c b/android/external/usb_modeswitch/usb_modeswitch/dispatcher.c new file mode 100755 index 0000000..c38ae31 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/dispatcher.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011-2016 Josua Dietze, usb_modeswitch version 2.3.0 + * Contains code under + * Copyright (c) 2010 Wojciech A. Koszek <wkoszek@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <jim.h> + +/* RAW is defined to the complete Tcl code in that file: */ +#include "usb_modeswitch.string" + +#define MAX_ARGSIZE 1024 + +int main(int argc, char **argv) +{ + int i, retval; + char arg[MAX_ARGSIZE]; + char arglist[MAX_ARGSIZE]; + + Jim_Interp *interp; + + interp = NULL; + arglist[0] = '\0'; + + for (i=1; i<argc; i++) { + if (strlen(argv[i]) > MAX_ARGSIZE-4) { + printf("Argument #%d extends maximum size, skip it\n", i); + continue; + } + if ( (strlen(arglist) + strlen(argv[i])) > MAX_ARGSIZE-4) { + printf("Argument #%d would extend maximum list size, skip it\n", i); + continue; + } + sprintf(arg,"{%s} ",argv[i]); + strncat(arglist,arg,MAX_ARGSIZE-1); + } + + char code[sizeof(RAW) + sizeof(arglist) + 28]; + sprintf(code, "set argv {%s}\nset argc %d\n", arglist, argc-1); + strncat(code, RAW, sizeof(RAW)); + + /* Create Jim instance */ + interp = Jim_CreateInterp(); + assert(interp != NULL && "Could not create interpreter!"); + + /* Register base commands, actually implementing Tcl */ + Jim_RegisterCoreCommands(interp); + + /* Initialize any static extensions */ + Jim_InitStaticExtensions(interp); + + /* Evaluate the script that's now in "code" */ + retval = Jim_Eval(interp, code); + if (retval < 0) + printf("Evaluation returned error %d\n", retval); + + /* Free the interpreter */ + Jim_FreeInterp(interp); + return (EXIT_SUCCESS); +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/AUTHORS b/android/external/usb_modeswitch/usb_modeswitch/jim/AUTHORS new file mode 100755 index 0000000..73413a5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/AUTHORS @@ -0,0 +1,41 @@ +Salvatore Sanfilippo <antirez@invece.org> + +with the help (patches, bug reports, ideas, extensions) of: + +Pat Thoyts +Clemens Hintze + +See also the ChangeLog and README files for other credits. + +DESIGN CREDITS: + +some of the idea inside Jim are the fruit of long discussions +inside the Tclers chat room. The feedback of the Tcl +comunity in general, and of the members of the Tcl Core Team, was +very important to avoid mistakes: I used the great experience of +this people as a test for some of the ideas I put into Jim. +Bad ideas tend to be demolished in no time by good engineers. + +Also the following ideas are due to the following authors: + +- Jim locals were originally proposed by Miguel Sofer, I (SS) added + the feature that make they similar to lexical scoped closures + using capturing of the local variables value if no explicit + intialization is provided. + +- The [lmap] command is my (SS) design, but I incorporated inside the + command an interesting idea of Donal K. Fellows that proposed that + the [continue] command may be used to skip the accumulation of the + current-iteartion result, providing in one command the power of + [map] and [filter] together. + + +ChangeLog committers to be identified. Tentative list: + +antirez - Salvatore Sanfilippo <antirez@gmail.com> +patthoyts - Pat Thoyts <patthoyts@users.sf.net> +oharboe - �yvind Harboe - soyvind.harboe@zylin.com +Andrew Lunn <andrew@lunn.ch> +Duane Ellis <openocd@duaneellis.com> +Uwe Klein <uklein@klein-messgeraete.de> +Clemens Hintze ml-jim@qiao.in-berlin.de aka chi diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/LICENSE b/android/external/usb_modeswitch/usb_modeswitch/jim/LICENSE new file mode 100755 index 0000000..d5b9ecb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/LICENSE @@ -0,0 +1,45 @@ +Unless explicitly stated, all files within Jim repository are released +under following license: + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/Makefile.in b/android/external/usb_modeswitch/usb_modeswitch/jim/Makefile.in new file mode 100755 index 0000000..0191c83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/Makefile.in @@ -0,0 +1,198 @@ +# Tools +CC ?= @CCACHE@ @CC@ +CXX = @CCACHE@ @CXX@ +RANLIB = @RANLIB@ +AR = @AR@ +STRIP = @STRIP@ + +# Configuration + +SH_CFLAGS ?= @SH_CFLAGS@ +SH_LDFLAGS ?= @SH_LDFLAGS@ +SHOBJ_CFLAGS ?= @SHOBJ_CFLAGS@ +SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS@ +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +LDFLAGS = @LDFLAGS@ +LDLIBS += @LDLIBS@ +exec_prefix ?= @exec_prefix@ +prefix ?= @prefix@ + +CC += -D_GNU_SOURCE -Wall $(OPTIM) -I. +CXX += -D_GNU_SOURCE -Wall $(OPTIM) -I. +@if srcdir != . +CFLAGS += -I@srcdir@ +CXXFLAGS += -I@srcdir@ +VPATH := @srcdir@ +@endif + +@if JIM_STATICLIB +LIBJIM := libjim.a +@else +LIBJIM := libjim.so +SH_LIBJIM := $(LIBJIM) +CC += $(SH_CFLAGS) +CXX += $(SH_CFLAGS) +DEF_LD_PATH := @LD_LIBRARY_PATH@=`pwd` +@endif + +@if HAVE_CXX_EXTENSIONS +JIMSH_CC := $(CXX) $(CXXFLAGS) +@else +JIMSH_CC := $(CC) $(CFLAGS) +@endif + +OBJS := _load-static-exts.o jim-subcmd.o jim-interactive.o jim-format.o jim.o utf8.o jimregexp.o \ + @EXTRA_OBJS@ @C_EXT_OBJS@ @TCL_EXT_OBJS@ + +JIMSH := jimsh@EXEEXT@ + +all: $(JIMSH) @C_EXT_SHOBJS@ + +# Create C extensions from pure Tcl extensions +.SUFFIXES: .tcl +.tcl.o: + @tclsh@ @srcdir@/make-c-ext.tcl $< >_$*.c || ( rm _$*.c; exit 1) + $(CC) $(CFLAGS) -c -o $@ _$*.c || ( rm _$*.c; exit 1) + @rm -f _$*.c + +docs: Tcl.html + +$(JIMSH): $(LIBJIM) jimsh.o initjimsh.o + $(JIMSH_CC) @SH_LINKFLAGS@ $(LDFLAGS) -o $@ jimsh.o initjimsh.o $(LIBJIM) $(LDLIBS) + +@if JIM_INSTALL +install: all docs @TCL_EXTS@ install-exec + mkdir -p $(DESTDIR)$(prefix)/lib/jim + cp $(LIBJIM) $(DESTDIR)$(prefix)/lib + cp @srcdir@/README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@ $(DESTDIR)$(prefix)/lib/jim + mkdir -p $(DESTDIR)$(prefix)/include + cp @srcdir@/jim.h @srcdir@/jim-eventloop.h @srcdir@/jim-nvp.h @srcdir@/jim-signal.h \ + @srcdir@/jim-subcmd.h @srcdir@/jim-win32compat.h $(DESTDIR)$(prefix)/include + cp jim-config.h $(DESTDIR)$(prefix)/include + mkdir -p $(DESTDIR)$(prefix)/doc/jim + cp Tcl.html $(DESTDIR)$(prefix)/doc/jim + +install-exec: all + mkdir -p $(DESTDIR)$(prefix)/bin + cp $(JIMSH) $(DESTDIR)$(prefix)/bin + +uninstall: + rm -f $(DESTDIR)$(prefix)/bin/$(JIMSH) + rm -f $(DESTDIR)$(prefix)/lib/$(LIBJIM) + for i in README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@; do rm -f $(DESTDIR)$(prefix)/lib/jim/$$i; done + rm -f $(DESTDIR)$(prefix)/include/jim*.h + rm -f $(DESTDIR)$(prefix)/doc/jim/Tcl.html +@else +install install-exec uninstall: +@endif + +test: $(JIMSH) + $(DEF_LD_PATH) $(MAKE) -C @srcdir@/tests jimsh=`pwd`/jimsh + +$(OBJS): Makefile + +@if JIM_UTF8 +# Generate the unicode case mapping +utf8.o: _unicode_mapping.c + +_unicode_mapping.c: @srcdir@/UnicodeData.txt @srcdir@/parse-unidata.tcl + @tclsh@ @srcdir@/parse-unidata.tcl @srcdir@/UnicodeData.txt >$@ || ( rm $@; exit 1) +@endif + +_load-static-exts.c: @srcdir@/make-load-static-exts.tcl Makefile + @tclsh@ @srcdir@/make-load-static-exts.tcl @STATIC_EXTS@ >$@ || ( rm $@; exit 1) + +@if JIM_STATICLIB +$(LIBJIM): $(OBJS) + $(AR) cr $@ $(OBJS) + $(RANLIB) $@ +@else +$(LIBJIM): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $(OBJS) $(LDLIBS) +@endif + +# Note that $> $^ is for compatibility with both GNU make and BSD make +readdir.so: jim-readdir.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readdir.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readdir.o $(SH_LIBJIM) + +array.so: jim-array.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-array.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-array.o $(SH_LIBJIM) + +clock.so: jim-clock.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-clock.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-clock.o $(SH_LIBJIM) + +file.so: jim-file.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-file.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-file.o $(SH_LIBJIM) + +posix.so: jim-posix.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-posix.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-posix.o $(SH_LIBJIM) + +regexp.so: jim-regexp.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-regexp.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-regexp.o $(SH_LIBJIM) + +syslog.so: jim-syslog.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-syslog.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-syslog.o $(SH_LIBJIM) + +readline.so: jim-readline.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readline.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readline.o $(SH_LIBJIM) @LDLIBS_readline@ + +pack.so: jim-pack.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-pack.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-pack.o $(SH_LIBJIM) @LDLIBS_pack@ + +sqlite.so: jim-sqlite.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sqlite.o $(SH_LIBJIM) @LDLIBS_sqlite@ + +sqlite3.so: jim-sqlite3.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite3.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sqlite3.o $(SH_LIBJIM) @LDLIBS_sqlite3@ + +win32.so: jim-win32.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-win32.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-win32.o $(SH_LIBJIM) @LDLIBS_win32@ + +mk.so: jim-mk.cpp + $(CXX) $(CXXFLAGS) $(SHOBJ_CFLAGS) -c -o jim-mk.o $> $^ + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-mk.o $(SH_LIBJIM) @LDLIBS_mk@ + +sdl.so: jim-sdl.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sdl.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sdl.o $(SH_LIBJIM) @LDLIBS_sdl@ + +Tcl.html: jim_tcl.txt + @tclsh@ @srcdir@/make-index $> $^ | asciidoc -o $@ -d manpage - || cp @srcdir@/Tcl_shipped.html Tcl.html + +clean: + rm -f *.o *.so lib*.a $(JIMSH) Tcl.html _*.c + +distclean: clean + rm -f jimautoconf.h jim-config.h Makefile config.log autosetup/jimsh0.c autosetup/jimsh0@EXEEXT@ + +ship: Tcl.html + cp $< Tcl_shipped.html + +# automake compatibility. do nothing for all these targets +EMPTY_AUTOMAKE_TARGETS := dvi pdf ps info html tags ctags mostlyclean maintainer-clean check installcheck installdirs \ + install-pdf install-ps install-info install-html -install-dvi uninstall install-data +.PHONY: $(EMPTY_AUTOMAKE_TARGETS) +$(EMPTY_AUTOMAKE_TARGETS): + +# automake compatibility - install sources from the current dir to $(distdir) +distdir_full := $(shell cd $(distdir); pwd) +distdir: + cd "@srcdir@"; git ls-files | cpio -pdmu $(distdir_full) + +reconfig: + CC='@CC@' @AUTOREMAKE@ + +lib: $(LIBJIM) diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/README b/android/external/usb_modeswitch/usb_modeswitch/jim/README new file mode 100755 index 0000000..8acacc4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/README @@ -0,0 +1,235 @@ +The Jim Interpreter + +A small-footprint implementation of the Tcl programming language. + +-------------------------------------------------------------------------------- +WHAT IS JIM? +-------------------------------------------------------------------------------- + +Jim is a small footprint implementation of the Tcl programming language +written from scratch. Currently Jim Tcl is very feature complete with +an extensive test suite (see the tests directory). +There are some Tcl commands and features which are not implemented +(and likely never will be), including namespaces, traces and Tk. However +Jim Tcl offers a number of both Tcl8.5 and Tcl8.6 features ({*}, dict, lassign, +tailcall and optional UTF-8 support) and some unique features. +These unique features include [lambda] with garbage collection, a general GC/references +system, arrays as syntax sugar for [dict]tionaries, object-based I/O and more. + +Other common features of the Tcl programming language are present, like +the "everything is a string" behaviour, implemented internally as +dual ported objects to ensure that the execution time does not reflect +the semantic of the language :) + +-------------------------------------------------------------------------------- +WHEN JIM CAN BE USEFUL? +-------------------------------------------------------------------------------- + +1) If you are writing an application, and want to make it scriptable, with +Jim you have a way to do it that does not require to link your application +with a big system. You can include the Jim source directly in your project +and use the Jim API to write the glue code that makes your application +scriptable in Jim, with the following advantages: + +- Jim is not the next "little language", but it's a Tcl implementation. + You can reuse your knowledge if you already Tcl skills, or enjoy + the availability of documentation, books, web resources, ... + (for example check my online Tcl book at http://www.invece.org/tclwise) + +- Jim is simple, 14k lines of core code. If you want to adapt it you can hack + the source code to meet the needs of your application. It makes you + able to have scripting for default, and avoid external dependences. + + Having scripting support *inside*, and in a way that a given version + of your program always gets shipped a given version of Jim, you can + write part of your application in Jim itself. Like it happens for + Emacs/Elisp, or Gimp/Scheme, both this applications have the interpreter + inside. + +- Jim is Tcl, and Tcl looks like a configuration file if you want. So + if you use Jim you have also a flexible syntax for your config file. + This is a valid Tcl script: + + set MyFeature on + ifssl { + set SslPort 45000 + use compression + } + + It looks like a configuration file, but if you implement the [ifssl] + and [use] commands, it's a valid Tcl script. + +- Tcl scales with the user. Not all know it, but Tcl is so powerful that + you can reprogram the language in itself. Jim support this features + of the Tcl programming language. You can write new control structures, + use the flexible data types it offers (Lists are a central data structure, + with Dictionaries that are also lists). Still Tcl is simpler for the + casual programmer, especially if compared to other languages offering + small footprint implementations (like Scheme and FORTH). + +- Because of the Tcl semantic (pass by value, everything is a command + since there are no reserved words), there is a nice API to glue + your application with Jim. See under the Jim Tcl manual for more detail. + +- Jim is supported. If you need commercial software, contact the original author + at 'antirez@gmail.com' or the current maintainer at 'steveb@workware.net.au'. + +2) The other "field" where Jim can be useful is obviously embedded systems. + +3) We are working to make Jim as feature-complete as possible, thanks to + dynamically loaded extensions it may stay as little as it is today + but able to do interesting things for you. So it's not excluded that + in the future Jim will be an option as general purpose language. + But don't mind, for this there is already the mainstream Tcl + implementation ;). + +-------------------------------------------------------------------------------- +HOW BIG IS IT? +-------------------------------------------------------------------------------- + +Jim with the default extensions configured and compiled with -Os is about 130k. +Without any extensions, it is about 85k. + +-------------------------------------------------------------------------------- +HOW FAST IS IT? +-------------------------------------------------------------------------------- + +Jim is in most code faster than Tcl7.6p2 (latest 7.x version), +and slower than Tcl 8.4.x. You can expect pretty decent performance +for such a little interpreter. + +If you want a more precise measure, there is 'bench.tcl' inside this +distribution that will run both under Jim and Tcl, so just execute +it with both the interpreters and see what you get :) + +-------------------------------------------------------------------------------- +HOW TO COMPILE +-------------------------------------------------------------------------------- + +Jim was tested under Linux, FreeBSD, MacosX, eCos, QNX, Windows XP (mingw, MVC). + +To compile jim itself try: + + ./configure + make + +-------------------------------------------------------------------------------- +EXTENSIONS +-------------------------------------------------------------------------------- + +Many optional extensions are included. Some are C extensions and others are pure Tcl. +Form more information, try: + + ./configure --help + +-------------------------------------------------------------------------------- +HOW TO EMBED JIM INTO APPLICATIONS +-------------------------------------------------------------------------------- + +See the "examples.api" directory + +-------------------------------------------------------------------------------- +HOW TO WRITE EXTENSIONS FOR JIM +-------------------------------------------------------------------------------- + +See the extensions shipped with Jim, jim-readline.c, jim-clock.c, glob.tcl and oo.tcl + +-------------------------------------------------------------------------------- +COPYRIGHT and LICENSE +-------------------------------------------------------------------------------- + +Unless explicitly stated, all files within Jim repository are released +under following license: + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + */ +-------------------------------------------------------------------------------- +HISTORY +-------------------------------------------------------------------------------- + +"first Jim goal: to vent my need to hack on Tcl." + +And actually this is exactly why I started Jim, in the first days +of Jenuary 2005. After a month of hacking Jim was able to run +simple scripts, now, after two months it started to be clear to +me that it was not just the next toy to throw away but something +that may evolve into a real interpreter. In the same time +Pat Thoyts and Clemens Hintze started to contribute code, so that +the development of new core commands was faster, and also more +people hacking on the same code had as result fixes in the API, +C macros, and so on. + +Currently we are at the point that the core interpreter is almost finished +and it is entering the Beta stage. There is to add some other core command, +to do a code review to ensure quality of all the parts and to write +documentation. + +We already started to work on extensions like OOP, event loop, +I/O, networking, regexp. Some extensions are already ready for +prime time, like the Sqlite extension and the ANSI I/O. + +------------------------------------------------------------------------------ +Thanks to... +------------------------------------------------------------------------------ + +- First of all, thanks to every guy that are listed in the AUTHORS file, + that directly helped with code and ideas. Also check the ChangeLog + file for additional credits about patches or bug reports. +- Elisa Manara that helped me to select this ill conceived name for + an interpreter. +- Many people on the Tclers Chat that helped me to explore issues + about the use and the implementation of the Tcl programming language. +- David Welton for the tech info sharing and our chats about + programming languages design and the ability of software to "scale down". +- Martin S. Weber for the great help with Solaris issues, debugging of + problems with [load] on this arch, 64bit tests. +- The authors of "valgrind", for this wonderful tool, that helped me a + lot to fix bugs in minutes instead of hours. + + +---- +Enjoy! +Salvatore Sanfilippo +10 Mar 2005 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch b/android/external/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch new file mode 100755 index 0000000..7f3ae41 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch @@ -0,0 +1,6 @@ +The content of this folder is customized for shipping with usb_modeswitch; +for the original source see: + +http://repo.or.cz/w/jimtcl.git + +This is version 0.72 of jimtcl diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/auto.def b/android/external/usb_modeswitch/usb_modeswitch/jim/auto.def new file mode 100755 index 0000000..2cdb85c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/auto.def @@ -0,0 +1,436 @@ +# vim:se syn=tcl: +# + +# Note: modules which support options *must* be included before 'options' +use cc cc-shared + +options { + utf8 => "include support for utf8-encoded strings" + lineedit=1 => "disable line editing" + references=1 => "disable support for references" + math => "include support for math functions" + ipv6 => "include ipv6 support in the aio extension" + maintainer => {enable the [debug] command and JimPanic} + full => "Enable some optional features: ipv6, math, utf8, binary, oo, tree" + with-jim-shared shared => "build a shared library instead of a static library" + jim-regexp => "use the built-in (Tcl-compatible) regexp, even if POSIX regex is available" + with-jim-ext: {with-ext:"ext1 ext2 ..."} => { + Specify additional jim extensions to include. + These are enabled by default: + + aio - ANSI I/O, including open and socket + eventloop - after, vwait, update + array - Tcl-compatible array command + clock - Tcl-compatible clock command + exec - Tcl-compatible exec command + file - Tcl-compatible file command + glob - Tcl-compatible glob command + readdir - Required for glob + package - Package management with the package command + load - Load binary extensions at runtime with load or package + posix - Posix APIs including os.fork, os.wait, pid + regexp - Tcl-compatible regexp, regsub commands + signal - Signal handling + stdlib - Built-in commands including lassign, lambda, alias + syslog - System logging with syslog + tclcompat - Tcl compatible read, gets, puts, parray, case, ... + + These are disabled by default: + + nvp - Name-value pairs C-only API + oo - Jim OO extension + tree - OO tree structure, similar to tcllib ::struct::tree + binary - Tcl-compatible 'binary' command + readline - Interface to libreadline + rlprompt - Tcl wrapper around the readline extension + mk - Interface to Metakit + sqlite - Interface to sqlite + sqlite3 - Interface to sqlite3 + win32 - Interface to win32 + } + with-out-jim-ext: {without-ext:"default|ext1 ext2 ..."} => { + Specify jim extensions to exclude. + If 'default' is given, the default extensions will not be added. + } + with-jim-extmod: {with-mod:"ext1 ext2 ..."} => { + Specify jim extensions to build as separate modules (either C or Tcl). + Note that not all extensions can be built as loadable modules. + } + # To help out openocd with automake + install-jim=1 +} + +cc-check-types "long long" + +cc-check-includes sys/socket.h netinet/in.h arpa/inet.h netdb.h +cc-check-includes sys/un.h dlfcn.h unistd.h crt_externs.h + +define LDLIBS "" + +# Haiku needs -lnetwork, Solaris needs -lnsl +if {[cc-check-function-in-lib inet_ntop {nsl network}]} { + # This does nothing if no libs are needed + cc-with [list -libs [get-define lib_inet_ntop]] + define-append LDLIBS [get-define lib_inet_ntop] +} +# Solaris needs -lsocket, Windows needs -lwsock32 +if {[cc-check-function-in-lib socket socket]} { + define-append LDLIBS [get-define lib_socket] +} + +cc-check-functions ualarm lstat fork vfork system select +cc-check-functions backtrace geteuid mkstemp realpath strptime gettimeofday +cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist +cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes +if {[cc-check-functions sysinfo]} { + cc-with {-includes sys/sysinfo.h} { + cc-check-members "struct sysinfo.uptime" + } +} + +define TCL_LIBRARY [get-define prefix]/lib/jim + +lassign [split [get-define host] -] host_cpu host_vendor host_os +# Scrub revision from the host_os +regsub -all {[0-9.]} $host_os {} host_os + +switch -glob -- $host_os { + mingw* { + # We provide our own implementation of dlopen for mingw32 + define-feature dlopen-compat + define-feature winconsole + define TCL_PLATFORM_OS $host_os + define TCL_PLATFORM_PLATFORM windows + define TCL_PLATFORM_PATH_SEPARATOR {;} + } + default { + # Note that cygwin is considered a unix platform + define TCL_PLATFORM_OS $host_os + define TCL_PLATFORM_PLATFORM unix + define TCL_PLATFORM_PATH_SEPARATOR : + } +} + +# Find some tools +cc-check-tools ar ranlib strip +define tclsh [info nameofexecutable] + +if {![cc-check-functions _NSGetEnviron]} { + msg-checking "Checking environ declared in unistd.h..." + if {[cctest -cflags -D_GNU_SOURCE -includes unistd.h -code {char **ep = environ;}]} { + define NO_ENVIRON_EXTERN + msg-result "yes" + } else { + msg-result "no" + } +} + +# Windows has a mkdir with no permission arg +cc-check-includes sys/types.h sys/stat.h +msg-checking "Checking for mkdir with one arg..." +if {[cctest -includes {sys/types.h sys/stat.h} -code {mkdir("/dummy");}]} { + define HAVE_MKDIR_ONE_ARG + msg-result yes +} else { + msg-result no +} + +# autosetup can't handle C++ libraries +proc check-metakit {} { + set found 0 + cc-with {-lang c++} { + msg-checking "Checking for Metakit..." + if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} { + msg-result ok + define lib_mk -lmk4 + incr found + } else { + msg-result "not found" + } + } + return $found +} + +set extra_objs {} +set jimregexp 0 + +if {[opt-bool utf8 full]} { + msg-result "Enabling UTF-8" + define JIM_UTF8 + incr jimregexp +} else { + define JIM_UTF8 0 +} +if {[opt-bool maintainer]} { + msg-result "Enabling maintainer settings" + define JIM_MAINTAINER +} +if {[opt-bool math full]} { + msg-result "Enabling math functions" + define JIM_MATH_FUNCTIONS + cc-check-function-in-lib sin m + define-append LDLIBS [get-define lib_sin] +} +if {[opt-bool ipv6 full]} { + msg-result "Enabling IPv6" + define JIM_IPV6 +} +if {[opt-bool lineedit full]} { + if {([cc-check-includes termios.h] && [cc-check-functions isatty]) || [have-feature winconsole]} { + msg-result "Enabling line editing" + define USE_LINENOISE + lappend extra_objs linenoise.o + } +} +if {[opt-bool references]} { + msg-result "Enabling references" + define JIM_REFERENCES +} +if {[opt-bool shared with-jim-shared]} { + msg-result "Building shared library" +} else { + msg-result "Building static library" + define JIM_STATICLIB +} +define JIM_INSTALL [opt-bool install-jim] + +# Note: Extension handling is mapped directly from the configure.ac +# implementation + +set without [join [opt-val {without-ext with-out-jim-ext}]] +set withext [join [opt-val {with-ext with-jim-ext}]] +set withmod [join [opt-val {with-mod with-jim-extmod}]] + +# Tcl extensions +set ext_tcl "stdlib glob tclcompat tree rlprompt oo binary" +# Native extensions +set ext_c "load package readdir array clock exec file posix regexp signal aio eventloop pack syslog nvp readline mk sqlite sqlite3 win32 sdl" + +# C++ extensions +set ext_cxx "mk" + +# Tcl extensions which can be modules +set ext_tcl_mod "glob tree rlprompt oo binary" +# Native extensions which can be modules +set ext_c_mod "readdir array clock file posix regexp syslog readline pack mk sqlite sqlite3 win32 sdl" + +# All extensions +set ext_all [concat $ext_c $ext_tcl] + +# Default static extensions +set ext_default "stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog" + +if {[opt-bool full]} { + lappend ext_default tree binary +} + +if {$without eq "default"} { + set ext_default stdlib + set without {} +} + +# Check valid extension names +foreach i [concat $withext $without $withmod] { + if {$i ni $ext_all} { + user-error "Unknown extension: $i" + } +} + +# needs_xxx="expression" means that the expr must eval to 1 to select the extension +# dep_xxx="yyy zzz" means that if xxx is selected, so is yyy and zzz +set dep(glob) readdir +set dep(rlprompt) readline +set dep(tree) oo +set dep(binary) pack + +set needs(exec) {expr {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]}} +set needs(load) {expr {[cc-check-function-in-lib dlopen dl] || [have-feature dlopen-compat]}} +set libdep(load) lib_dlopen +set needs(posix) {have-feature waitpid} +set needs(readdir) {have-feature opendir} +set needs(readline) {cc-check-function-in-lib readline readline} +set libdep(readline) lib_readline +set needs(signal) {expr {[have-feature sigaction] && [have-feature vfork]}} +set needs(mk) {check-metakit} +set libdep(mk) lib_mk +set needs(sqlite) {cc-check-function-in-lib sqlite_open sqlite} +set libdep(sqlite) lib_sqlite_open +set needs(sqlite3) {cc-check-function-in-lib sqlite3_open sqlite3} +set libdep(sqlite3) lib_sqlite3_open +set needs(syslog) {have-feature syslog} +set needs(win32) {have-feature windows} +set needs(sdl) {expr {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]}} +set libdep(sdl) {lib_SDL_SetVideoMode lib_rectangleRGBA} + +# First handle dependencies. If an extension is enabled, also enable its dependency +foreach i [concat $ext_default $withext] { + if {$i in $without} { + continue + } + if {[info exists dep($i)]} { + lappend withext {*}$dep($i) + } +} + +foreach i $withmod { + if {[info exists dep($i)]} { + # Theoretically, a mod could depend upon something which must be static + # If already configured static, don't make it a module + foreach d $dep($i) { + if {$d ni $withext} { + lappend withmod $d + } + } + } +} + +# Now that we know what the platform supports: + +# For all known extensions: +# - If it is disabled, remove it +# - Otherwise, check to see if it's pre-requisites are met +# - If yes, add it if it is enabled or is a default +# - If no, error if it is enabled, or do nothing otherwise +# - Modules may be either C or Tcl + +set extmodtcl {} +set extmod {} +set ext {} + +foreach i [lsort $ext_all] { + # First discard the extension if disabled or not enabled + if {$i in $without} { + msg-result "Extension $i...disabled" + continue + } + if {$i ni [concat $withext $withmod $ext_default]} { + msg-result "Extension $i...not enabled" + continue + } + + # Check dependencies + set met 1 + if {[info exists needs($i)]} { + set met [eval $needs($i)] + } + + define LDLIBS_$i "" + + msg-checking "Extension $i..." + + # Selected as a module? + if {$i in $withmod} { + if {$i in $ext_tcl_mod} { + # Easy, a Tcl module + msg-result "tcl" + lappend extmodtcl $i + continue + } + if {$i ni $ext_c_mod} { + user-error "not a module" + } + if {!$met} { + user-error "dependencies not met" + } + msg-result "module" + lappend extmod $i + if {[info exists libdep($i)]} { + foreach j $libdep($i) { + define-append LDLIBS_$i [get-define $j ""] + } + } + continue + } + + # Selected as a static extension? + if {$i in $withext} { + if {!$met} { + user-error "dependencies not met" + } + msg-result "enabled" + } elseif {$i in $ext_default} { + if {!$met} { + msg-result "disabled (dependencies)" + continue + } + msg-result "enabled (default)" + } else { + continue + } + + lappend ext $i + if {[info exists libdep($i)]} { + foreach j $libdep($i) { + define-append LDLIBS [get-define $j ""] + } + } +} + +if {[have-feature windows]} { + lappend extra_objs jim-win32compat.o + + if {$extmod ne "" && [get-define JIM_LIBTYPE] eq "static"} { + user-error "cygwin/mingw require --shared for dynamic modules" + } +} + +if {"regexp" in "$ext $extmod"} { + # No regcomp means we need to use the built-in version + if {![have-feature regcomp]} { + incr jimregexp + } +} + +if {$jimregexp || [opt-bool jim-regexp]} { + msg-result "Using built-in regexp" + define JIM_REGEXP + + # If the built-in regexp overrides the system regcomp, etc. + # jim must be built shared so that the correct symbols are found + if {"regexp" in $extmod && [get-define JIM_LIBTYPE] eq "static" && [have-feature regcomp]} { + user-error "Must use --shared with regexp module and built-in regexp" + } +} +if {"load" ni $ext} { + # If we don't have load, no need to support shared objects + define SH_LINKFLAGS "" +} + +msg-result "Jim static extensions: [lsort $ext]" +if {$extmodtcl ne ""} { + msg-result "Jim Tcl extensions: [lsort $extmodtcl]" +} +if {$extmod ne ""} { + msg-result "Jim dynamic extensions: [lsort $extmod]" +} + +# Separate out the static extensions into C and Tcl +set ext_static_c {} +set ext_static_tcl {} +foreach e $ext { + define jim_ext_$e + if {$e in $ext_tcl} { + lappend ext_static_tcl $e + } else { + lappend ext_static_c $e + } +} + +# If there are any static C++ extensions, jimsh must be linked using +# the C++ compiler +foreach e $ext_static_c { + if {$e in $ext_cxx} { + define HAVE_CXX_EXTENSIONS + } +} + +define STATIC_EXTS [concat $ext_static_c $ext_static_tcl] +define C_EXT_OBJS [prefix jim- [suffix .o $ext_static_c]] +define TCL_EXT_OBJS [suffix .o $ext_static_tcl] +define C_EXT_SHOBJS [suffix .so $extmod] +define TCL_EXTS [suffix .tcl $extmodtcl] +define EXTRA_OBJS $extra_objs + +make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -none * +make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_*} +make-template Makefile.in diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE new file mode 100755 index 0000000..4fe636c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE @@ -0,0 +1,35 @@ +Unless explicitly stated, all files which form part of autosetup +are released under the following license: + +--------------------------------------------------------------------- +autosetup - A build environment "autoconfigurator" + +Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/> + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE +SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of WorkWare Systems. diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup new file mode 100755 index 0000000..c7f69a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup @@ -0,0 +1 @@ +This is autosetup v0.6.3. See http://msteveb.github.com/autosetup/ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup new file mode 100755 index 0000000..b1134c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup @@ -0,0 +1,1820 @@ +#!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: +# \ +dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" + +set autosetup(version) 0.6.3 + +# Can be set to 1 to debug early-init problems +set autosetup(debug) 0 + +################################################################## +# +# Main flow of control, option handling +# +proc main {argv} { + global autosetup define + + # There are 3 potential directories involved: + # 1. The directory containing autosetup (this script) + # 2. The directory containing auto.def + # 3. The current directory + + # From this we need to determine: + # a. The path to this script (and related support files) + # b. The path to auto.def + # c. The build directory, where output files are created + + # This is also complicated by the fact that autosetup may + # have been run via the configure wrapper ([getenv WRAPPER] is set) + + # Here are the rules. + # a. This script is $::argv0 + # => dir, prog, exe, libdir + # b. auto.def is in the directory containing the configure wrapper, + # otherwise it is in the current directory. + # => srcdir, autodef + # c. The build directory is the current directory + # => builddir, [pwd] + + # 'misc' is needed before we can do anything, so set a temporary libdir + # in case this is the development version + set autosetup(libdir) [file dirname $::argv0]/lib + use misc + + # (a) + set autosetup(dir) [realdir [file dirname [realpath $::argv0]]] + set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]] + set autosetup(exe) [getenv WRAPPER $autosetup(prog)] + if {$autosetup(installed)} { + set autosetup(libdir) $autosetup(dir) + } else { + set autosetup(libdir) [file join $autosetup(dir) lib] + } + autosetup_add_dep $autosetup(prog) + + # (b) + if {[getenv WRAPPER ""] eq ""} { + # Invoked directly + set autosetup(srcdir) [pwd] + } else { + # Invoked via the configure wrapper + set autosetup(srcdir) [file dirname $autosetup(exe)] + } + set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def] + + # (c) + set autosetup(builddir) [pwd] + + set autosetup(argv) $argv + set autosetup(cmdline) {} + set autosetup(options) {} + set autosetup(optionhelp) {} + set autosetup(showhelp) 0 + + # Parse options + use getopt + + array set ::useropts [getopt argv] + + #"=Core Options:" + options-add { + help:=local => "display help and options. Optionally specify a module name, such as --help=system" + version => "display the version of autosetup" + ref:=text manual:=text + reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'" + debug => "display debugging output as autosetup runs" + install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)" + force init => "create an initial 'configure' script if none exists" + # Undocumented options + option-checking=1 + nopager + quiet + timing + conf: + } + + #parray ::useropts + if {[opt-bool version]} { + puts $autosetup(version) + exit 0 + } + + # autosetup --conf=alternate-auto.def + if {[opt-val conf] ne ""} { + set autosetup(autodef) [opt-val conf] + } + + # Debugging output (set this early) + incr autosetup(debug) [opt-bool debug] + incr autosetup(force) [opt-bool force] + incr autosetup(msg-quiet) [opt-bool quiet] + incr autosetup(msg-timing) [opt-bool timing] + + # If the local module exists, source it now to allow for + # project-local customisations + if {[file exists $autosetup(libdir)/local.tcl]} { + use local + } + + if {[opt-val help] ne ""} { + incr autosetup(showhelp) + use help + autosetup_help [opt-val help] + } + + if {[opt-val {manual ref reference}] ne ""} { + use help + autosetup_reference [opt-val {manual ref reference}] + } + + if {[opt-bool init]} { + use init + autosetup_init + } + + if {[opt-val install] ne ""} { + use install + autosetup_install [opt-val install] + } + + if {![file exists $autosetup(autodef)]} { + # Check for invalid option first + options {} + user-error "No auto.def found in $autosetup(srcdir)" + } + + # Parse extra arguments into autosetup(cmdline) + foreach arg $argv { + if {[regexp {([^=]*)=(.*)} $arg -> n v]} { + dict set autosetup(cmdline) $n $v + define $n $v + } else { + user-error "Unexpected parameter: $arg" + } + } + + autosetup_add_dep $autosetup(autodef) + + set cmd [file-normalize $autosetup(exe)] + foreach arg $autosetup(argv) { + append cmd " [quote-if-needed $arg]" + } + define AUTOREMAKE $cmd + + # Log how we were invoked + configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" + + source $autosetup(autodef) + + # Could warn here if options {} was not specified + + show-notices + + if {$autosetup(debug)} { + parray define + } + + exit 0 +} + +# @opt-bool option ... +# +# Check each of the named, boolean options and return 1 if any of them have +# been set by the user. +# +proc opt-bool {args} { + option-check-names {*}$args + opt_bool ::useropts {*}$args +} + +# @opt-val option-list ?default=""? +# +# Returns a list containing all the values given for the non-boolean options in 'option-list'. +# There will be one entry in the list for each option given by the user, including if the +# same option was used multiple times. +# If only a single value is required, use something like: +# +## lindex [opt-val $names] end +# +# If no options were set, $default is returned (exactly, not as a list). +# +proc opt-val {names {default ""}} { + option-check-names {*}$names + join [opt_val ::useropts $names $default] +} + +proc option-check-names {args} { + foreach o $args { + if {$o ni $::autosetup(options)} { + autosetup-error "Request for undeclared option --$o" + } + } +} + +# Parse the option definition in $opts and update +# ::useropts() and ::autosetup(optionhelp) appropriately +# +proc options-add {opts {header ""}} { + global useropts autosetup + + # First weed out comment lines + set realopts {} + foreach line [split $opts \n] { + if {![string match "#*" [string trimleft $line]]} { + append realopts $line \n + } + } + set opts $realopts + + for {set i 0} {$i < [llength $opts]} {incr i} { + set opt [lindex $opts $i] + if {[string match =* $opt]} { + # This is a special heading + lappend autosetup(optionhelp) $opt "" + set header {} + continue + } + + #puts "i=$i, opt=$opt" + regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value + if {$name in $autosetup(options)} { + autosetup-error "Option $name already specified" + } + + #puts "$opt => $name $colon $equal $value" + + # Find the corresponding value in the user options + # and set the default if necessary + if {[string match "-*" $opt]} { + # This is a documentation-only option, like "-C <dir>" + set opthelp $opt + } elseif {$colon eq ""} { + # Boolean option + lappend autosetup(options) $name + + if {![info exists useropts($name)]} { + set useropts($name) $value + } + if {$value eq "1"} { + set opthelp "--disable-$name" + } else { + set opthelp "--$name" + } + } else { + # String option. + lappend autosetup(options) $name + + if {$equal eq "="} { + if {[info exists useropts($name)]} { + # If the user specified the option with no value, the value will be "1" + # Replace with the default + if {$useropts($name) eq "1"} { + set useropts($name) $value + } + } + set opthelp "--$name?=$value?" + } else { + set opthelp "--$name=$value" + } + } + + # Now create the help for this option if appropriate + if {[lindex $opts $i+1] eq "=>"} { + set desc [lindex $opts $i+2] + #string match \n* $desc + if {$header ne ""} { + lappend autosetup(optionhelp) $header "" + set header "" + } + # A multi-line description + lappend autosetup(optionhelp) $opthelp $desc + incr i 2 + } + } +} + +# @module-options optionlist +# +# Like 'options', but used within a module. +proc module-options {opts} { + set header "" + if {$::autosetup(showhelp) > 1 && [llength $opts]} { + set header "Module Options:" + } + options-add $opts $header + + if {$::autosetup(showhelp)} { + # Ensure that the module isn't executed on --help + # We are running under eval or source, so use break + # to prevent further execution + #return -code break -level 2 + return -code break + } +} + +proc max {a b} { + expr {$a > $b ? $a : $b} +} + +proc options-wrap-desc {text length firstprefix nextprefix initial} { + set len $initial + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} + +proc options-show {} { + # Determine the max option width + set max 0 + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt] || [string match \n* $desc]} { + continue + } + set max [max $max [string length $opt]] + } + set indent [string repeat " " [expr $max+4]] + set cols [getenv COLUMNS 80] + catch { + lassign [exec stty size] rows cols + } + incr cols -1 + # Now output + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt]} { + puts [string range $opt 1 end] + continue + } + puts -nonewline " [format %-${max}s $opt]" + if {[string match \n* $desc]} { + puts $desc + } else { + options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2] + } + } +} + +# @options options-spec +# +# Specifies configuration-time options which may be selected by the user +# and checked with opt-val and opt-bool. The format of options-spec follows. +# +# A boolean option is of the form: +# +## name[=0|1] => "Description of this boolean option" +# +# The default is name=0, meaning that the option is disabled by default. +# If name=1 is used to make the option enabled by default, the description should reflect +# that with text like "Disable support for ...". +# +# An argument option (one which takes a parameter) is of the form: +# +## name:[=]value => "Description of this option" +# +# If the name:value form is used, the value must be provided with the option (as --name=myvalue). +# If the name:=value form is used, the value is optional and the given value is used as the default +# if is not provided. +# +# Undocumented options are also supported by omitting the "=> description. +# These options are not displayed with --help and can be useful for internal options or as aliases. +# +# For example, --disable-lfs is an alias for --disable=largefile: +# +## lfs=1 largefile=1 => "Disable large file support" +# +proc options {optlist} { + # Allow options as a list or args + options-add $optlist "Local Options:" + + if {$::autosetup(showhelp)} { + options-show + exit 0 + } + + # Check for invalid options + if {[opt-bool option-checking]} { + foreach o [array names ::useropts] { + if {$o ni $::autosetup(options)} { + user-error "Unknown option --$o" + } + } + } +} + +proc config_guess {} { + if {[file-isexec $::autosetup(dir)/config.guess]} { + exec-with-stderr sh $::autosetup(dir)/config.guess + } else { + configlog "No config.guess, so using uname" + string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r] + } +} + +proc config_sub {alias} { + if {[file-isexec $::autosetup(dir)/config.sub]} { + exec-with-stderr sh $::autosetup(dir)/config.sub $alias + } else { + return $alias + } +} + +# @define name ?value=1? +# +# Defines the named variable to the given value. +# These (name, value) pairs represent the results of the configuration check +# and are available to be checked, modified and substituted. +# +proc define {name {value 1}} { + set ::define($name) $value + #dputs "$name <= $value" +} + +# @define-append name value ... +# +# Appends the given value(s) to the given 'defined' variable. +# If the variable is not defined or empty, it is set to $value. +# Otherwise the value is appended, separated by a space. +# Any extra values are similarly appended. +# If any value is already contained in the variable (as a substring) it is omitted. +# +proc define-append {name args} { + if {[get-define $name ""] ne ""} { + # Make a token attempt to avoid duplicates + foreach arg $args { + if {[string first $arg $::define($name)] == -1} { + append ::define($name) " " $arg + } + } + } else { + set ::define($name) [join $args] + } + #dputs "$name += [join $args] => $::define($name)" +} + +# @get-define name ?default=0? +# +# Returns the current value of the 'defined' variable, or $default +# if not set. +# +proc get-define {name {default 0}} { + if {[info exists ::define($name)]} { + #dputs "$name => $::define($name)" + return $::define($name) + } + #dputs "$name => $default" + return $default +} + +# @is-defined name +# +# Returns 1 if the given variable is defined. +# +proc is-defined {name} { + info exists ::define($name) +} + +# @all-defines +# +# Returns a dictionary (name value list) of all defined variables. +# +# This is suitable for use with 'dict', 'array set' or 'foreach' +# and allows for arbitrary processing of the defined variables. +# +proc all-defines {} { + array get ::define +} + + +# @get-env name default +# +# If $name was specified on the command line, return it. +# If $name was set in the environment, return it. +# Otherwise return $default. +# +proc get-env {name default} { + if {[dict exists $::autosetup(cmdline) $name]} { + return [dict get $::autosetup(cmdline) $name] + } + getenv $name $default +} + +# @env-is-set name +# +# Returns 1 if the $name was specified on the command line or in the environment. +# Note that an empty environment variable is not considered to be set. +# +proc env-is-set {name} { + if {[dict exists $::autosetup(cmdline) $name]} { + return 1 + } + if {[getenv $name ""] ne ""} { + return 1 + } + return 0 +} + +# @readfile filename ?default=""? +# +# Return the contents of the file, without the trailing newline. +# If the doesn't exist or can't be read, returns $default. +# +proc readfile {filename {default_value ""}} { + set result $default_value + catch { + set f [open $filename] + set result [read -nonewline $f] + close $f + } + return $result +} + +# @writefile filename value +# +# Creates the given file containing $value. +# Does not add an extra newline. +# +proc writefile {filename value} { + set f [open $filename w] + puts -nonewline $f $value + close $f +} + +proc quote-if-needed {str} { + if {[string match {*[\" ]*} $str]} { + return \"[string map [list \" \\" \\ \\\\] $str]\" + } + return $str +} + +proc quote-argv {argv} { + set args {} + foreach arg $argv { + lappend args [quote-if-needed $arg] + } + join $args +} + +# @suffix suf list +# +# Takes a list and returns a new list with $suf appended +# to each element +# +## suffix .c {a b c} => {a.c b.c c.c} +# +proc suffix {suf list} { + set result {} + foreach p $list { + lappend result $p$suf + } + return $result +} + +# @prefix pre list +# +# Takes a list and returns a new list with $pre prepended +# to each element +# +## prefix jim- {a.c b.c} => {jim-a.c jim-b.c} +# +proc prefix {pre list} { + set result {} + foreach p $list { + lappend result $pre$p + } + return $result +} + +# @find-executable name +# +# Searches the path for an executable with the given name. +# Note that the name may include some parameters, e.g. "cc -mbig-endian", +# in which case the parameters are ignored. +# Returns 1 if found, or 0 if not. +# +proc find-executable {name} { + # Ignore any parameters + set name [lindex $name 0] + if {$name eq ""} { + # The empty string is never a valid executable + return 0 + } + foreach p [split-path] { + dputs "Looking for $name in $p" + set exec [file join $p $name] + if {[file-isexec $exec]} { + dputs "Found $name -> $exec" + return 1 + } + } + return 0 +} + +# @find-an-executable ?-required? name ... +# +# Given a list of possible executable names, +# searches for one of these on the path. +# +# Returns the name found, or "" if none found. +# If the first parameter is '-required', an error is generated +# if no executable is found. +# +proc find-an-executable {args} { + set required 0 + if {[lindex $args 0] eq "-required"} { + set args [lrange $args 1 end] + incr required + } + foreach name $args { + if {[find-executable $name]} { + return $name + } + } + if {$required} { + if {[llength $args] == 1} { + user-error "failed to find: [join $args]" + } else { + user-error "failed to find one of: [join $args]" + } + } + return "" +} + +# @configlog msg +# +# Writes the given message to the configuration log, config.log +# +proc configlog {msg} { + if {![info exists ::autosetup(logfh)]} { + set ::autosetup(logfh) [open config.log w] + } + puts $::autosetup(logfh) $msg +} + +# @msg-checking msg +# +# Writes the message with no newline to stdout. +# +proc msg-checking {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts -nonewline $msg + set ::autosetup(msg-checking) 1 + } +} + +# @msg-result msg +# +# Writes the message to stdout. +# +proc msg-result {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts $msg + set ::autosetup(msg-checking) 0 + show-notices + } +} + +# @msg-quiet command ... +# +# msg-quiet evaluates it's arguments as a command with output +# from msg-checking and msg-result suppressed. +# +# This is useful if a check needs to run a subcheck which isn't +# of interest to the user. +proc msg-quiet {args} { + incr ::autosetup(msg-quiet) + set rc [uplevel 1 $args] + incr ::autosetup(msg-quiet) -1 + return $rc +} + +# Will be overridden by 'use misc' +proc error-stacktrace {msg} { + return $msg +} + +proc error-location {msg} { + return $msg +} + +################################################################## +# +# Debugging output +# +proc dputs {msg} { + if {$::autosetup(debug)} { + puts $msg + } +} + +################################################################## +# +# User and system warnings and errors +# +# Usage errors such as wrong command line options + +# @user-error msg +# +# Indicate incorrect usage to the user, including if required components +# or features are not found. +# autosetup exits with a non-zero return code. +# +proc user-error {msg} { + show-notices + puts stderr "Error: $msg" + puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options" + exit 1 +} + +# @user-notice msg +# +# Output the given message to stderr. +# +proc user-notice {msg} { + lappend ::autosetup(notices) $msg +} + +# Incorrect usage in the auto.def file. Identify the location. +proc autosetup-error {msg} { + show-notices + puts stderr [error-location $msg] + exit 1 +} + +proc show-notices {} { + if {$::autosetup(msg-checking)} { + puts "" + set ::autosetup(msg-checking) 0 + } + flush stdout + if {[info exists ::autosetup(notices)]} { + puts stderr [join $::autosetup(notices) \n] + unset ::autosetup(notices) + } +} + +proc maybe-show-timestamp {} { + if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} { + puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]] + } +} + +proc autosetup_version {} { + return "autosetup v$::autosetup(version)" +} + +################################################################## +# +# Directory/path handling +# + +proc realdir {dir} { + set oldpwd [pwd] + cd $dir + set pwd [pwd] + cd $oldpwd + return $pwd +} + +# Follow symlinks until we get to something which is not a symlink +proc realpath {path} { + while {1} { + if {[catch { + set path [file link $path] + }]} { + # Not a link + break + } + } + return $path +} + +# Convert absolute path, $path into a path relative +# to the given directory (or the current dir, if not given). +# +proc relative-path {path {pwd {}}} { + set diff 0 + set same 0 + set newf {} + set prefix {} + set path [file-normalize $path] + if {$pwd eq ""} { + set pwd [pwd] + } else { + set pwd [file-normalize $pwd] + } + + if {$path eq $pwd} { + return . + } + + # Try to make the filename relative to the current dir + foreach p [split $pwd /] f [split $path /] { + if {$p ne $f} { + incr diff + } elseif {!$diff} { + incr same + } + if {$diff} { + if {$p ne ""} { + # Add .. for sibling or parent dir + lappend prefix .. + } + if {$f ne ""} { + lappend newf $f + } + } + } + if {$same == 1 || [llength $prefix] > 3} { + return $path + } + + file join [join $prefix /] [join $newf /] +} + +# Add filename as a dependency to rerun autosetup +# The name will be normalised (converted to a full path) +# +proc autosetup_add_dep {filename} { + lappend ::autosetup(deps) [file-normalize $filename] +} + +################################################################## +# +# Library module support +# + +# @use module ... +# +# Load the given library modules. +# e.g. use cc cc-shared +# +proc use {args} { + foreach m $args { + if {[info exists ::libmodule($m)]} { + continue + } + set ::libmodule($m) 1 + if {[info exists ::modsource($m)]} { + uplevel #0 eval $::modsource($m) + } else { + set source $::autosetup(libdir)/${m}.tcl + if {[file exists $source]} { + uplevel #0 [list source $source] + autosetup_add_dep $source + } else { + puts "Looking for $source" + autosetup-error "use: No such module: $m" + } + } + } +} + +# Initial settings +set autosetup(exe) $::argv0 +set autosetup(istcl) 1 +set autosetup(start) [clock millis] +set autosetup(installed) 0 +set autosetup(msg-checking) 0 +set autosetup(msg-quiet) 0 + +# Embedded modules are inserted below here +set autosetup(installed) 1 +# ----- module asciidoc-formatting ----- + +set modsource(asciidoc-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# asciidoc format + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc code {text} { + foreach line [parse_code_block $text] { + puts " $line" + } + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc indent {text} { + puts " :: " + puts [para $text] +} +proc defn {first args} { + set sep "" + if {$first ne ""} { + puts "${first}::" + } else { + puts " :: " + } + set defn [string trim [join $args \n]] + regsub -all "\n\n" $defn "\n ::\n" defn + puts $defn +} +} + +# ----- module formatting ----- + +set modsource(formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides common text formatting + +# This is designed for documenation which looks like: +# code {...} +# or +# code { +# ... +# ... +# } +# In the second case, we need to work out the indenting +# and strip it from all lines but preserve the remaining indenting. +# Note that all lines need to be indented with the same initial +# spaces/tabs. +# +# Returns a list of lines with the indenting removed. +# +proc parse_code_block {text} { + # If the text begins with newline, take the following text, + # otherwise just return the original + if {![regexp "^\n(.*)" $text -> text]} { + return [list [string trim $text]] + } + + # And trip spaces off the end + set text [string trimright $text] + + set min 100 + # Examine each line to determine the minimum indent + foreach line [split $text \n] { + if {$line eq ""} { + # Ignore empty lines for the indent calculation + continue + } + regexp "^(\[ \t\]*)" $line -> indent + set len [string length $indent] + if {$len < $min} { + set min $len + } + } + + # Now make a list of lines with this indent removed + set lines {} + foreach line [split $text \n] { + lappend lines [string range $line $min end] + } + + # Return the result + return $lines +} +} + +# ----- module getopt ----- + +set modsource(getopt) { +# Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Simple getopt module + +# Parse everything out of the argv list which looks like an option +# Knows about --enable-thing and --disable-thing as alternatives for --thing=0 or --thing=1 +# Everything which doesn't look like an option, or is after --, is left unchanged +proc getopt {argvname} { + upvar $argvname argv + set nargv {} + + for {set i 0} {$i < [llength $argv]} {incr i} { + set arg [lindex $argv $i] + + #dputs arg=$arg + + if {$arg eq "--"} { + # End of options + incr i + lappend nargv {*}[lrange $argv $i end] + break + } + + if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} { + lappend opts($name) $value + } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} { + if {$prefix eq "disable-"} { + set value 0 + } else { + set value 1 + } + lappend opts($name) $value + } else { + lappend nargv $arg + } + } + + #puts "getopt: argv=[join $argv] => [join $nargv]" + #parray opts + + set argv $nargv + + return [array get opts] +} + +proc opt_val {optarrayname options {default {}}} { + upvar $optarrayname opts + + set result {} + + foreach o $options { + if {[info exists opts($o)]} { + lappend result {*}$opts($o) + } + } + if {[llength $result] == 0} { + return $default + } + return $result +} + +proc opt_bool {optarrayname args} { + upvar $optarrayname opts + + # Support the args being passed as a list + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + foreach o $args { + if {[info exists opts($o)]} { + if {"1" in $opts($o) || "yes" in $opts($o)} { + return 1 + } + } + } + return 0 +} +} + +# ----- module help ----- + +set modsource(help) { +# Copyright (c) 2010 WorkWare Systems http://workware.net.au/ +# All rights reserved + +# Module which provides usage, help and the command reference + +proc autosetup_help {what} { + use_pager + + puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" + puts "This is [autosetup_version], a build environment \"autoconfigurator\"" + puts "See the documentation online at http://msteveb.github.com/autosetup/\n" + + if {$what eq "local"} { + if {[file exists $::autosetup(autodef)]} { + # This relies on auto.def having a call to 'options' + # which will display options and quit + source $::autosetup(autodef) + } else { + options-show + } + } else { + incr ::autosetup(showhelp) + if {[catch {use $what}]} { + user-error "Unknown module: $what" + } else { + options-show + } + } + exit 0 +} + +# If not already paged and stdout is a tty, pipe the output through the pager +# This is done by reinvoking autosetup with --nopager added +proc use_pager {} { + if {![opt-bool nopager] && [getenv PAGER ""] ne "" && ![string match "not a tty" [exec tty]]} { + catch { + exec [info nameofexecutable] $::argv0 --nopager {*}$::argv | [getenv PAGER] >@stdout <@stdin 2>/dev/null + } + exit 0 + } +} + +# Outputs the autosetup references in one of several formats +proc autosetup_reference {{type text}} { + + use_pager + + switch -glob -- $type { + wiki {use wiki-formatting} + ascii* {use asciidoc-formatting} + md - markdown {use markdown-formatting} + default {use text-formatting} + } + + title "[autosetup_version] -- Command Reference" + + section {Introduction} + + p { + See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup' + } + + p { + 'autosetup' provides a number of built-in commands which + are documented below. These may be used from 'auto.def' to test + for features, define variables, create files from templates and + other similar actions. + } + + automf_command_reference + + exit 0 +} + +proc autosetup_output_block {type lines} { + if {[llength $lines]} { + switch $type { + code { + codelines $lines + } + p { + p [join $lines] + } + list { + foreach line $lines { + bullet $line + } + nl + } + } + } +} + +# Generate a command reference from inline documentation +proc automf_command_reference {} { + lappend files $::autosetup(prog) + lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]] + + section "Core Commands" + set type p + set lines {} + set cmd {} + + foreach file $files { + set f [open $file] + while {![eof $f]} { + set line [gets $f] + + # Find lines starting with "# @*" and continuing through the remaining comment lines + if {![regexp {^# @(.*)} $line -> cmd]} { + continue + } + + # Synopsis or command? + if {$cmd eq "synopsis:"} { + section "Module: [file rootname [file tail $file]]" + } else { + subsection $cmd + } + + set lines {} + set type p + + # Now the description + while {![eof $f]} { + set line [gets $f] + + if {![regexp {^#(#)? ?(.*)} $line -> hash cmd]} { + break + } + if {$hash eq "#"} { + set t code + } elseif {[regexp {^- (.*)} $cmd -> cmd]} { + set t list + } else { + set t p + } + + #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd" + + if {$t ne $type || $cmd eq ""} { + # Finish the current block + autosetup_output_block $type $lines + set lines {} + set type $t + } + if {$cmd ne ""} { + lappend lines $cmd + } + } + + autosetup_output_block $type $lines + } + close $f + } +} +} + +# ----- module init ----- + +set modsource(init) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module to help create auto.def and configure + +proc autosetup_init {} { + set create_configure 1 + if {[file exists configure]} { + if {!$::autosetup(force)} { + # Could this be an autosetup configure? + if {![string match "*\nWRAPPER=*" [readfile configure]]} { + puts "I see configure, but not created by autosetup, so I won't overwrite it." + puts "Use autosetup --init --force to overwrite." + set create_configure 0 + } + } else { + puts "I will overwrite the existing configure because you used --force." + } + } else { + puts "I don't see configure, so I will create it." + } + if {$create_configure} { + if {!$::autosetup(installed)} { + user-notice "Warning: Initialising from the development version of autosetup" + + writefile configure "#!/bin/sh\nWRAPPER=\"\$0\" exec $::autosetup(dir)/autosetup \"\$@\"\n" + } else { + writefile configure \ +{#!/bin/sh +dir="`dirname "$0"`/autosetup" +WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" +} + } + catch {exec chmod 755 configure} + } + if {![file exists auto.def]} { + puts "I don't see auto.def, so I will create a default one." + writefile auto.def {# Initial auto.def created by 'autosetup --init' + +use cc + +# Add any user options here +options { +} + +make-config-header config.h +make-template Makefile.in +} + } + if {![file exists Makefile.in]} { + puts "Note: I don't see Makefile.in. You will probably need to create one." + } + + exit 0 +} +} + +# ----- module install ----- + +set modsource(install) { +# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which can install autosetup + +proc autosetup_install {dir} { + if {[catch { + cd $dir + file mkdir autosetup + + set f [open autosetup/autosetup w] + + set publicmodules {} + + # First the main script, but only up until "CUT HERE" + set in [open $::autosetup(dir)/autosetup] + while {[gets $in buf] >= 0} { + if {$buf ne "##-- CUT HERE --##"} { + puts $f $buf + continue + } + + # Insert the static modules here + # i.e. those which don't contain @synopsis: + puts $f "set autosetup(installed) 1" + foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] { + set buf [readfile $file] + if {[string match "*\n# @synopsis:*" $buf]} { + lappend publicmodules $file + continue + } + set modname [file rootname [file tail $file]] + puts $f "# ----- module $modname -----" + puts $f "\nset modsource($modname) \{" + puts $f $buf + puts $f "\}\n" + } + } + close $in + close $f + exec chmod 755 autosetup/autosetup + + # Install public modules + foreach file $publicmodules { + autosetup_install_file $file autosetup + } + + # Install support files + foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} { + autosetup_install_file $::autosetup(dir)/$file autosetup + } + exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh + + writefile autosetup/README.autosetup \ + "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n" + + } error]} { + user-error "Failed to install autosetup: $error" + } + puts "Installed [autosetup_version] to autosetup/" + catch {exec [info nameofexecutable] autosetup/autosetup --init >@stdout 2>@stderr} + + exit 0 +} + +# Append the contents of $file to filehandle $f +proc autosetup_install_append {f file} { + set in [open $file] + puts $f [read $in] + close $in +} + +proc autosetup_install_file {file dir} { + if {![file exists $file]} { + error "Missing installation file '$file'" + } + writefile [file join $dir [file tail $file]] [readfile $file]\n +} + +if {$::autosetup(installed)} { + user-error "autosetup can only be installed from development source, not from installed copy" +} +} + +# ----- module markdown-formatting ----- + +set modsource(markdown-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# markdown format (kramdown syntax) + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " text + regsub -all {([^a-zA-Z])'([^']*)'} $text {\1**`\2`**} text + regsub -all {^'([^']*)'} $text {**`\1`**} text + regsub -all {(http[^ \t\n]*)} $text {[\1](\1)} text + return $text +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc codelines {lines} { + puts "~~~~~~~~~~~~" + foreach line $lines { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc code {text} { + puts "~~~~~~~~~~~~" + foreach line [parse_code_block $text] { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + puts "### `$text`" + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc defn {first args} { + puts "^" + set defn [string trim [join $args \n]] + if {$first ne ""} { + puts "**${first}**" + puts -nonewline ": " + regsub -all "\n\n" $defn "\n: " defn + } + puts "$defn" +} +} + +# ----- module misc ----- + +set modsource(misc) { +# Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module containing misc procs useful to modules +# Largely for platform compatibility + +set autosetup(istcl) [info exists ::tcl_library] +set autosetup(iswin) [string equal windows $tcl_platform(platform)] + +if {$autosetup(iswin)} { + # mingw/windows separates $PATH with semicolons + # and doesn't have an executable bit + proc split-path {} { + split [getenv PATH .] {;} + } + proc file-isexec {exec} { + # Basic test for windows. We ignore .bat + if {[file isfile $exec] || [file isfile $exec.exe]} { + return 1 + } + return 0 + } +} else { + # unix separates $PATH with colons and has and executable bit + proc split-path {} { + split [getenv PATH .] : + } + proc file-isexec {exec} { + file executable $exec + } +} + +# Assume that exec can return stdout and stderr +proc exec-with-stderr {args} { + exec {*}$args 2>@1 +} + +if {$autosetup(istcl)} { + # Tcl doesn't have the env command + proc getenv {name args} { + if {[info exists ::env($name)]} { + return $::env($name) + } + if {[llength $args]} { + return [lindex $args 0] + } + return -code error "environment variable \"$name\" does not exist" + } +} elseif {$autosetup(iswin)} { + # On Windows, backslash convert all environment variables + # (Assume that Tcl does this for us) + proc getenv {name args} { + string map {\\ /} [env $name {*}$args] + } +} else { + # Jim on unix is simple + alias getenv env +} + +# In case 'file normalize' doesn't exist +# +proc file-normalize {path} { + if {[catch {file normalize $path} result]} { + if {$path eq ""} { + return "" + } + set oldpwd [pwd] + if {[file isdir $path]} { + cd $path + set result [pwd] + } else { + cd [file dirname $path] + set result [file join [pwd] [file tail $path]] + } + cd $oldpwd + } + return $result +} + +# If everything is working properly, the only errors which occur +# should be generated in user code (e.g. auto.def). +# By default, we only want to show the error location in user code. +# We use [info frame] to achieve this, but it works differently on Tcl and Jim. +# +# This is designed to be called for incorrect usage in auto.def, via autosetup-error +# +proc error-location {msg} { + if {$::autosetup(debug)} { + return -code error $msg + } + # Search back through the stack trace for the first error in a .def file + for {set i 1} {$i < [info level]} {incr i} { + if {$::autosetup(istcl)} { + array set info [info frame -$i] + } else { + lassign [info frame -$i] info(caller) info(file) info(line) + } + if {[string match *.def $info(file)]} { + return "[relative-path $info(file)]:$info(line): Error: $msg" + } + #puts "Skipping $info(file):$info(line)" + } + return $msg +} + +# Similar to error-location, but called when user code generates an error +# In this case we want to show the stack trace in user code, but not in autosetup code +# (unless --debug is enabled) +# +proc error-stacktrace {msg} { + if {$::autosetup(istcl)} { + if {[regexp {file "([^ ]*)" line ([0-9]*)} $::errorInfo dummy file line]} { + return "[relative-path $file]:$line $msg\n$::errorInfo" + } + return $::errorInfo + } else { + # Prepend a live stacktrace to the error stacktrace, omitting the current level + set stacktrace [concat [info stacktrace] [lrange [stacktrace] 3 end]] + + if {!$::autosetup(debug)} { + # Omit any levels from autosetup or with no file + set newstacktrace {} + foreach {p f l} $stacktrace { + if {[string match "*autosetup" $f] || $f eq ""} { + #puts "Skipping $p $f:$l" + continue + } + lappend newstacktrace $p $f $l + } + set stacktrace $newstacktrace + } + + # Convert filenames to relative paths + set newstacktrace {} + foreach {p f l} $stacktrace { + lappend newstacktrace $p [relative-path $f] $l + } + lassign $newstacktrace p f l + if {$f ne ""} { + set prefix "$f:$l: " + } else { + set prefix "" + } + + return "${prefix}Error: $msg\n[stackdump $newstacktrace]" + } +} +} + +# ----- module text-formatting ----- + +set modsource(text-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting + +use formatting + +proc wordwrap {text length {firstprefix ""} {nextprefix ""}} { + set len 0 + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + + # Use man-page conventions for highlighting 'quoted' and *quoted* + # single words. + # Use x^Hx for *bold* and _^Hx for 'underline'. + # + # less and more will both understand this. + # Pipe through 'col -b' to remove them. + if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "_\b&" word + append word $dot + } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "&\b&" word + append word $dot + } + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} +proc title {text} { + underline [string trim $text] = + nl +} +proc p {text} { + wordwrap $text 80 + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[string trim $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + wordwrap $text 76 " * " " " +} +proc indent {text} { + wordwrap $text 76 " " " " +} +proc defn {first args} { + if {$first ne ""} { + underline " $first" ~ + } + foreach p $args { + if {$p ne ""} { + indent $p + } + } +} +} + +# ----- module wiki-formatting ----- + +set modsource(wiki-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# wiki.tcl.tk format output + +use formatting + +proc joinlines {text} { + set lines {} + foreach l [split [string trim $text] \n] { + lappend lines [string trim $l] + } + join $lines +} +proc p {text} { + puts [joinlines $text] + puts "" +} +proc title {text} { + puts "*** [joinlines $text] ***" + puts "" +} +proc codelines {lines} { + puts "======" + foreach line $lines { + puts " $line" + } + puts "======" +} +proc code {text} { + puts "======" + foreach line [parse_code_block $text] { + puts " $line" + } + puts "======" +} +proc nl {} { +} +proc section {text} { + puts "'''$text'''" + puts "" +} +proc subsection {text} { + puts "''$text''" + puts "" +} +proc bullet {text} { + puts " * [joinlines $text]" +} +proc indent {text} { + puts " : [joinlines $text]" +} +proc defn {first args} { + if {$first ne ""} { + indent '''$first''' + } + + foreach p $args { + p $p + } +} +} + + +################################################################## +# +# Entry/Exit +# +if {$autosetup(debug)} { + main $argv +} +if {[catch {main $argv} msg] == 1} { + show-notices + puts stderr [error-stacktrace $msg] + if {!$autosetup(debug) && !$autosetup(istcl)} { + puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace" + } + exit 1 +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl new file mode 100755 index 0000000..e8e5e86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl @@ -0,0 +1,77 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# Provides a library of common tests on top of the 'cc' module. + +use cc + +module-options {} + +# @cc-check-lfs +# +# The equivalent of the AC_SYS_LARGEFILE macro +# +# defines 'HAVE_LFS' if LFS is available, +# and defines '_FILE_OFFSET_BITS=64' if necessary +# +# Returns 1 if 'LFS' is available or 0 otherwise +# +proc cc-check-lfs {} { + cc-check-includes sys/types.h + msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..." + set lfs 1 + if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} { + msg-result no + } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} { + define _FILE_OFFSET_BITS 64 + msg-result yes + } else { + set lfs 0 + msg-result none + } + define-feature lfs $lfs + return $lfs +} + +# @cc-check-endian +# +# The equivalent of the AC_C_BIGENDIAN macro +# +# defines 'HAVE_BIG_ENDIAN' if endian is known to be big, +# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little. +# +# Returns 1 if determined, or 0 if not. +# +proc cc-check-endian {} { + cc-check-includes sys/types.h sys/param.h + set rc 0 + msg-checking "Checking endian..." + cc-with {-includes {sys/types.h sys/param.h}} { + if {[cctest -code { + #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != BIG_ENDIAN + #error little + #endif + }]} { + define-feature big-endian + msg-result "big" + set rc 1 + } elseif {[cctest -code { + #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != LITTLE_ENDIAN + #error big + #endif + }]} { + define-feature little-endian + msg-result "little" + set rc 1 + } else { + msg-result "unknown" + } + } + return $rc +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl new file mode 100755 index 0000000..1e77440 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl @@ -0,0 +1,63 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-shared' module provides support for shared libraries and shared objects. +# It defines the following variables: +# +## SH_CFLAGS Flags to use compiling sources destined for a shared library +## SH_LDFLAGS Flags to use linking a shared library +## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object +## SHOBJ_LDFLAGS Flags to use linking a shared object +## SH_LINKFLAGS Flags to use linking an executable which will load shared objects +## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries + +module-options {} + +foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LDFLAGS} { + define $i "" +} + +define LD_LIBRARY_PATH LD_LIBRARY_PATH + +switch -glob -- [get-define host] { + *-*-darwin* { + define SH_CFLAGS -dynamic + define SH_LDFLAGS "-dynamiclib" + define SHOBJ_CFLAGS "-dynamic -fno-common" + define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup" + define LD_LIBRARY_PATH DYLD_LIBRARY_PATH + } + *-*-ming* { + define SH_LDFLAGS -shared + define SHOBJ_LDFLAGS -shared + } + *-*-cygwin { + define SH_LDFLAGS -shared + define SHOBJ_LDFLAGS -shared + } + *-*-solaris* { + # XXX: These haven't been fully tested. + #define SH_LINKFLAGS -Wl,-export-dynamic + define SH_CFLAGS -Kpic + define SHOBJ_CFLAGS -Kpic + define SHOBJ_LDFLAGS "-G" + } + *-*-hpux { + # XXX: These haven't been tested + define SH_LINKFLAGS -Wl,+s + define SH_CFLAGS +z + define SHOBJ_CFLAGS "+O3 +z" + define SHOBJ_LDFLAGS -b + define LD_LIBRARY_PATH SHLIB_PATH + } + * { + # Generic Unix settings + define SH_LINKFLAGS -rdynamic + define SH_CFLAGS -fpic + define SH_LDFLAGS -shared + define SHOBJ_CFLAGS -fpic + define SHOBJ_LDFLAGS "-shared" + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl new file mode 100755 index 0000000..707e69c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl @@ -0,0 +1,660 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc' module supports checking various 'features' of the C or C++ +# compiler/linker environment. Common commands are cc-check-includes, +# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template. +# +# The following environment variables are used if set: +# +## CC - C compiler +## CXX - C++ compiler +## CCACHE - Set to "none" to disable automatic use of ccache +## CFLAGS - Additional C compiler flags +## CXXFLAGS - Additional C++ compiler flags +## LDFLAGS - Additional compiler flags during linking +## LIBS - Additional libraries to use (for all tests) +## CROSS - Tool prefix for cross compilation +# +# The following variables are defined from the corresponding +# environment variables if set. +# +## CPPFLAGS +## LINKFLAGS +## CC_FOR_BUILD +## LD + +use system + +module-options {} + +# Note that the return code is not meaningful +proc cc-check-something {name code} { + uplevel 1 $code +} + +# Checks for the existence of the given function by linking +# +proc cctest_function {function} { + cctest -link 1 -declare "extern void $function\(void);" -code "$function\();" +} + +# Checks for the existence of the given type by compiling +proc cctest_type {type} { + cctest -code "$type _x;" +} + +# Checks for the existence of the given type/structure member. +# e.g. "struct stat.st_mtime" +proc cctest_member {struct_member} { + lassign [split $struct_member .] struct member + cctest -code "static $struct _s; return sizeof(_s.$member);" +} + +# Checks for the existence of the given define by compiling +# +proc cctest_define {name} { + cctest -code "#ifndef $name\n#error not defined\n#endif" +} + +# Checks for the existence of the given name either as +# a macro (#define) or an rvalue (such as an enum) +# +proc cctest_decl {name} { + cctest -code "#ifndef $name\n(void)$name;\n#endif" +} + +# @cc-check-sizeof type ... +# +# Checks the size of the given types (between 1 and 32, inclusive). +# Defines a variable with the size determined, or "unknown" otherwise. +# e.g. for type 'long long', defines SIZEOF_LONG_LONG. +# Returns the size of the last type. +# +proc cc-check-sizeof {args} { + foreach type $args { + msg-checking "Checking for sizeof $type..." + set size unknown + # Try the most common sizes first + foreach i {4 8 1 2 16 32} { + if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} { + set size $i + break + } + } + msg-result $size + set define [feature-define-name $type SIZEOF_] + define $define $size + } + # Return the last result + get-define $define +} + +# Checks for each feature in $list by using the given script. +# +# When the script is evaluated, $each is set to the feature +# being checked, and $extra is set to any additional cctest args. +# +# Returns 1 if all features were found, or 0 otherwise. +proc cc-check-some-feature {list script} { + set ret 1 + foreach each $list { + if {![check-feature $each $script]} { + set ret 0 + } + } + return $ret +} + +# @cc-check-includes includes ... +# +# Checks that the given include files can be used +proc cc-check-includes {args} { + cc-check-some-feature $args { + cctest -includes $each + } +} + +# @cc-check-types type ... +# +# Checks that the types exist. +proc cc-check-types {args} { + cc-check-some-feature $args { + cctest_type $each + } +} + +# @cc-check-defines define ... +# +# Checks that the given preprocessor symbol is defined +proc cc-check-defines {args} { + cc-check-some-feature $args { + cctest_define $each + } +} + +# @cc-check-decls name ... +# +# Checks that each given name is either a preprocessor symbol or rvalue +# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx +# rather than HAVE_xxx +proc cc-check-decls {args} { + set ret 1 + foreach name $args { + msg-checking "Checking for $name..." + set r [cctest_decl $name] + define-feature "decl $name" $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + set ret 0 + } + } + return $ret +} + +# @cc-check-functions function ... +# +# Checks that the given functions exist (can be linked) +proc cc-check-functions {args} { + cc-check-some-feature $args { + cctest_function $each + } +} + +# @cc-check-members type.member ... +# +# Checks that the given type/structure members exist. +# A structure member is of the form "struct stat.st_mtime" +proc cc-check-members {args} { + cc-check-some-feature $args { + cctest_member $each + } +} + +# @cc-check-function-in-lib function libs ?otherlibs? +# +# Checks that the given given function can be found in one of the libs. +# +# First checks for no library required, then checks each of the libraries +# in turn. +# +# If the function is found, the feature is defined and lib_$function is defined +# to -l$lib where the function was found, or "" if no library required. +# In addition, -l$lib is added to the LIBS define. +# +# If additional libraries may be needed for linking, they should be specified +# as $extralibs as "-lotherlib1 -lotherlib2". +# These libraries are not automatically added to LIBS. +# +# Returns 1 if found or 0 if not. +# +proc cc-check-function-in-lib {function libs {otherlibs {}}} { + msg-checking "Checking libs for $function..." + set found 0 + cc-with [list -libs $otherlibs] { + if {[cctest_function $function]} { + msg-result "none needed" + define lib_$function "" + incr found + } else { + foreach lib $libs { + cc-with [list -libs -l$lib] { + if {[cctest_function $function]} { + msg-result -l$lib + define lib_$function -l$lib + define-append LIBS -l$lib + incr found + break + } + } + } + } + } + if {$found} { + define [feature-define-name $function] + } else { + msg-result "no" + } + return $found +} + +# @cc-check-tools tool ... +# +# Checks for existence of the given compiler tools, taking +# into account any cross compilation prefix. +# +# For example, when checking for "ar", first AR is checked on the command +# line and then in the environment. If not found, "${host}-ar" or +# simply "ar" is assumed depending upon whether cross compiling. +# The path is searched for this executable, and if found AR is defined +# to the executable name. +# +# It is an error if the executable is not found. +# +proc cc-check-tools {args} { + foreach tool $args { + set TOOL [string toupper $tool] + set exe [get-env $TOOL [get-define cross]$tool] + if {![find-executable $exe]} { + user-error "Failed to find $exe" + } + define $TOOL $exe + } +} + +# @cc-check-progs prog ... +# +# Checks for existence of the given executables on the path. +# +# For example, when checking for "grep", the path is searched for +# the executable, 'grep', and if found GREP is defined as "grep". +# +# It the executable is not found, the variable is defined as false. +# Returns 1 if all programs were found, or 0 otherwise. +# +proc cc-check-progs {args} { + set failed 0 + foreach prog $args { + set PROG [string toupper $prog] + msg-checking "Checking for $prog..." + if {![find-executable $prog]} { + msg-result no + define $PROG false + incr failed + } else { + msg-result ok + define $PROG $prog + } + } + expr {!$failed} +} + +# Adds the given settings to $::autosetup(ccsettings) and +# returns the old settings. +# +proc cc-add-settings {settings} { + if {[llength $settings] % 2} { + autosetup-error "settings list is missing a value: $settings" + } + + set prev [cc-get-settings] + # workaround a bug in some versions of jimsh by forcing + # conversion of $prev to a list + llength $prev + + array set new $prev + + foreach {name value} $settings { + switch -exact -- $name { + -cflags - -includes { + # These are given as lists + lappend new($name) {*}$value + } + -declare { + lappend new($name) $value + } + -libs { + # Note that new libraries are added before previous libraries + set new($name) [list {*}$value {*}$new($name)] + } + -link - -lang { + set new($name) $value + } + -source - -sourcefile - -code { + # XXX: These probably are only valid directly from cctest + set new($name) $value + } + default { + autosetup-error "unknown cctest setting: $name" + } + } + } + + cc-store-settings [array get new] + + return $prev +} + +proc cc-store-settings {new} { + set ::autosetup(ccsettings) $new +} + +proc cc-get-settings {} { + return $::autosetup(ccsettings) +} + +# Similar to cc-add-settings, but each given setting +# simply replaces the existing value. +# +# Returns the previous settings +proc cc-update-settings {args} { + set prev [cc-get-settings] + cc-store-settings [dict merge $prev $args] + return $prev +} + +# @cc-with settings ?{ script }? +# +# Sets the given 'cctest' settings and then runs the tests in 'script'. +# Note that settings such as -lang replace the current setting, while +# those such as -includes are appended to the existing setting. +# +# If no script is given, the settings become the default for the remainder +# of the auto.def file. +# +## cc-with {-lang c++} { +## # This will check with the C++ compiler +## cc-check-types bool +## cc-with {-includes signal.h} { +## # This will check with the C++ compiler, signal.h and any existing includes. +## ... +## } +## # back to just the C++ compiler +## } +# +# The -libs setting is special in that newer values are added *before* earlier ones. +# +## cc-with {-libs {-lc -lm}} { +## cc-with {-libs -ldl} { +## cctest -libs -lsocket ... +## # libs will be in this order: -lsocket -ldl -lc -lm +## } +## } +proc cc-with {settings args} { + if {[llength $args] == 0} { + cc-add-settings $settings + } elseif {[llength $args] > 1} { + autosetup-error "usage: cc-with settings ?script?" + } else { + set save [cc-add-settings $settings] + set rc [catch {uplevel 1 [lindex $args 0]} result info] + cc-store-settings $save + if {$rc != 0} { + return $result -code [dict get $info -code] + } + return $result + } +} + +# @cctest ?settings? +# +# Low level C compiler checker. Compiles and or links a small C program +# according to the arguments and returns 1 if OK, or 0 if not. +# +# Supported settings are: +# +## -cflags cflags A list of flags to pass to the compiler +## -includes list A list of includes, e.g. {stdlib.h stdio.h} +## -declare code Code to declare before main() +## -link 1 Don't just compile, link too +## -lang c|c++ Use the C (default) or C++ compiler +## -libs liblist List of libraries to link, e.g. {-ldl -lm} +## -code code Code to compile in the body of main() +## -source code Compile a complete program. Ignore -includes, -declare and -code +## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] +# +# Unless -source or -sourcefile is specified, the C program looks like: +# +## #include <firstinclude> /* same for remaining includes in the list */ +## +## declare-code /* any code in -declare, verbatim */ +## +## int main(void) { +## code /* any code in -code, verbatim */ +## return 0; +## } +# +# Any failures are recorded in 'config.log' +# +proc cctest {args} { + set src conftest__.c + set tmp conftest__ + + # Easiest way to merge in the settings + cc-with $args { + array set opts [cc-get-settings] + } + + if {[info exists opts(-sourcefile)]} { + set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] + } + if {[info exists opts(-source)]} { + set lines $opts(-source) + } else { + foreach i $opts(-includes) { + if {$opts(-code) ne "" && ![feature-checked $i]} { + # Compiling real code with an unchecked header file + # Quickly (and silently) check for it now + + # Remove all -includes from settings before checking + set saveopts [cc-update-settings -includes {}] + msg-quiet cc-check-includes $i + cc-store-settings $saveopts + } + if {$opts(-code) eq "" || [have-feature $i]} { + lappend source "#include <$i>" + } + } + lappend source {*}$opts(-declare) + lappend source "int main(void) {" + lappend source $opts(-code) + lappend source "return 0;" + lappend source "}" + + set lines [join $source \n] + } + + # Build the command line + set cmdline {} + lappend cmdline {*}[get-define CCACHE] + switch -exact -- $opts(-lang) { + c++ { + lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] + } + c { + lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] + } + default { + autosetup-error "cctest called with unknown language: $opts(-lang)" + } + } + + if {!$opts(-link)} { + set tmp conftest__.o + lappend cmdline -c + } + lappend cmdline {*}$opts(-cflags) + + switch -glob -- [get-define host] { + *-*-darwin* { + # Don't generate .dSYM directories + lappend cmdline -gstabs + } + } + lappend cmdline $src -o $tmp {*}$opts(-libs) + + # At this point we have the complete command line and the + # complete source to be compiled. Get the result from cache if + # we can + if {[info exists ::cc_cache($cmdline,$lines)]} { + msg-checking "(cached) " + set ok $::cc_cache($cmdline,$lines) + if {$::autosetup(debug)} { + configlog "From cache (ok=$ok): [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + return $ok + } + + writefile $src $lines\n + + set ok 1 + if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} { + configlog "Failed: [join $cmdline]" + configlog $result + configlog "============" + configlog "The failed code was:" + configlog $lines + configlog "============" + set ok 0 + } elseif {$::autosetup(debug)} { + configlog "Compiled OK: [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + file delete $src + file delete $tmp + + # cache it + set ::cc_cache($cmdline,$lines) $ok + + return $ok +} + +# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*? +# +# Deprecated - see make-config-header +proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} { + user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead" + make-config-header $file -auto $autopatterns -bare $barepatterns +} + +# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ... +# +# Examines all defined variables which match the given patterns +# and writes an include file, $file, which defines each of these. +# Variables which match '-auto' are output as follows: +# - defines which have the value "0" are ignored. +# - defines which have integer values are defined as the integer value. +# - any other value is defined as a string, e.g. "value" +# Variables which match '-bare' are defined as-is. +# Variables which match '-str' are defined as a string, e.g. "value" +# Variables which match '-none' are omitted. +# +# Note that order is important. The first pattern which matches is selected +# Default behaviour is: +# +# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none * +# +# If the file would be unchanged, it is not written. +proc make-config-header {file args} { + set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]] + file mkdir [file dirname $file] + set lines {} + lappend lines "#ifndef $guard" + lappend lines "#define $guard" + + # Add some defaults + lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* + + foreach n [lsort [dict keys [all-defines]]] { + set value [get-define $n] + set type [calc-define-output-type $n $args] + switch -exact -- $type { + -bare { + # Just output the value unchanged + } + -none { + continue + } + -str { + set value \"$value\" + } + -auto { + # Automatically determine the type + if {$value eq "0"} { + lappend lines "/* #undef $n */" + continue + } + if {![string is integer -strict $value]} { + set value \"$value\" + } + } + "" { + continue + } + default { + autosetup-error "Unknown type in make-config-header: $type" + } + } + lappend lines "#define $n $value" + } + lappend lines "#endif" + set buf [join $lines \n] + write-if-changed $file $buf { + msg-result "Created $file" + } +} + +proc calc-define-output-type {name spec} { + foreach {type patterns} $spec { + foreach pattern $patterns { + if {[string match $pattern $name]} { + return $type + } + } + } + return "" +} + +# Initialise some values from the environment or commandline or default settings +foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} { + lassign $i var default + define $var [get-env $var $default] +} + +if {[env-is-set CC]} { + # Set by the user, so don't try anything else + set try [list [get-env CC ""]] +} else { + # Try some reasonable options + set try [list [get-define cross]cc [get-define cross]gcc] +} +define CC [find-an-executable {*}$try] +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CPP [get-env CPP "[get-define CC] -E"] + +# XXX: Could avoid looking for a C++ compiler until requested +# Note that if CXX isn't found, we just set it to "false". It might not be needed. +if {[env-is-set CXX]} { + define CXX [find-an-executable -required [get-env CXX ""]] +} else { + define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++ false] +} + +# CXXFLAGS default to CFLAGS if not specified +define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]] + +cc-check-tools ld + +# May need a CC_FOR_BUILD, so look for one +define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false] + +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CCACHE [find-an-executable [get-env CCACHE ccache]] + +# Initial cctest settings +cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}} + +msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]" +if {[get-define CXX] ne "false"} { + msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]" +} +msg-result "Build C compiler...[get-define CC_FOR_BUILD]" + +if {![cc-check-includes stdlib.h]} { + user-error "Compiler does not work. See config.log" +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess new file mode 100755 index 0000000..4c8f032 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess @@ -0,0 +1,1508 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to <config-patches@gnu.org> and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' HUP INT TERM + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" HUP INT PIPE TERM ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-tilera-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub new file mode 100755 index 0000000..320e303 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub @@ -0,0 +1,1739 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile-* | tilegx-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh new file mode 100755 index 0000000..7ef152a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh @@ -0,0 +1,17 @@ +#!/bin/sh +# Looks for a suitable tclsh or jimsh in the PATH +# If not found, builds a bootstrap jimsh from source +d=`dirname "$0"` +{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0 +PATH="$PATH:$d" +for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do + { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0 +done +echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" +./make-bootstrap-jim > $d/jimsh0.c +for cc in ${CC_FOR_BUILD:-cc} gcc; do + { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue + "$d/jimsh0" "$d/test-tclsh" && exit 0 +done +echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." +echo false diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl new file mode 100755 index 0000000..f05d05b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl @@ -0,0 +1,268 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# This module supports common system interrogation and options +# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEXT. +# +# It also support the 'feature' naming convention, where searching +# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H +# +module-options { + host:host-alias => {a complete or partial cpu-vendor-opsys for the system where + the application will run (defaults to the same value as --build)} + build:build-alias => {a complete or partial cpu-vendor-opsys for the system + where the application will be built (defaults to the + result of running config.guess)} + prefix:dir => {the target directory for the build (defaults to /usr/local)} + + # These (hidden) options are supported for autoconf/automake compatibility + exec-prefix: + bindir: + sbindir: + includedir: + mandir: + infodir: + libexecdir: + datadir: + libdir: + sysconfdir: + sharedstatedir: + localstatedir: + maintainer-mode=0 + dependency-tracking=0 +} + +# Returns 1 if exists, or 0 if not +# +proc check-feature {name code} { + msg-checking "Checking for $name..." + set r [uplevel 1 $code] + define-feature $name $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + } + return $r +} + +# @have-feature name ?default=0? +# +# Returns the value of the feature if defined, or $default if not. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc have-feature {name {default 0}} { + get-define [feature-define-name $name] $default +} + +# @define-feature name ?value=1? +# +# Sets the feature 'define' to the given value. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc define-feature {name {value 1}} { + define [feature-define-name $name] $value +} + +# @feature-checked name +# +# Returns 1 if the feature has been checked, whether true or not +# +proc feature-checked {name} { + is-defined [feature-define-name $name] +} + +# @feature-define-name name ?prefix=HAVE_? +# +# Converts a name to the corresponding define, +# e.g. sys/stat.h becomes HAVE_SYS_STAT_H. +# +# Converts * to P and all non-alphanumeric to underscore. +# +proc feature-define-name {name {prefix HAVE_}} { + string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _] +} + +# If $file doesn't exist, or it's contents are different than $buf, +# the file is written and $script is executed. +# Otherwise a "file is unchanged" message is displayed. +proc write-if-changed {file buf {script {}}} { + set old [readfile $file ""] + if {$old eq $buf && [file exists $file]} { + msg-result "$file is unchanged" + } else { + writefile $file $buf\n + uplevel 1 $script + } +} + +# @make-template template ?outfile? +# +# Reads the input file <srcdir>/$template and writes the output file $outfile. +# If $outfile is blank/omitted, $template should end with ".in" which +# is removed to create the output file name. +# +# Each pattern of the form @define@ is replaced the the corresponding +# define, if it exists, or left unchanged if not. +# +# The special value @srcdir@ is subsituted with the relative +# path to the source directory from the directory where the output +# file is created. Use @top_srcdir@ for the absolute path. +# +# Conditional sections may be specified as follows: +## @if name == value +## lines +## @else +## lines +## @endif +# +# Where 'name' is a defined variable name and @else is optional. +# If the expression does not match, all lines through '@endif' are ignored. +# +# The alternative forms may also be used: +## @if name +## @if name != value +# +# Where the first form is true if the variable is defined, but not empty or 0 +# +# Currently these expressions can't be nested. +# +proc make-template {template {out {}}} { + set infile [file join $::autosetup(srcdir) $template] + + if {![file exists $infile]} { + user-error "Template $template is missing" + } + + # Define this as late as possible + define AUTODEPS $::autosetup(deps) + + if {$out eq ""} { + if {[file ext $template] ne ".in"} { + autosetup-error "make_template $template has no target file and can't guess" + } + set out [file rootname $template] + } + + set outdir [file dirname $out] + + # Make sure the directory exists + file mkdir $outdir + + # Set up srcdir to be relative to the target dir + define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] + + set mapping {} + foreach {n v} [array get ::define] { + lappend mapping @$n@ $v + } + set result {} + foreach line [split [readfile $infile] \n] { + if {[info exists cond]} { + set l [string trimright $line] + if {$l eq "@endif"} { + unset cond + continue + } + if {$l eq "@else"} { + set cond [expr {!$cond}] + continue + } + if {$cond} { + lappend result $line + } + continue + } + if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} { + lassign $expression equal value + set varval [get-define $name ""] + if {$equal eq ""} { + set cond [expr {$varval ni {"" 0}}] + } else { + set cond [expr {$varval eq $value}] + if {$equal ne "=="} { + set cond [expr {!$cond}] + } + } + continue + } + lappend result $line + } + writefile $out [string map $mapping [join $result \n]]\n + + msg-result "Created [relative-path $out] from [relative-path $template]" +} + +# build/host tuples and cross-compilation prefix +set build [opt-val build] +define build_alias $build +if {$build eq ""} { + define build [config_guess] +} else { + define build [config_sub $build] +} + +set host [opt-val host] +define host_alias $host +if {$host eq ""} { + define host [get-define build] + set cross "" +} else { + define host [config_sub $host] + set cross $host- +} +define cross [get-env CROSS $cross] + +set prefix [opt-val prefix /usr/local] + +# These are for compatibility with autoconf +define target [get-define host] +define prefix $prefix +define builddir $autosetup(builddir) +define srcdir $autosetup(srcdir) +# Allow this to come from the environment +define top_srcdir [get-env top_srcdir [get-define srcdir]] + +# autoconf supports all of these +set exec_prefix [opt-val exec-prefix $prefix] +define exec_prefix $exec_prefix +foreach {name defpath} { + bindir /bin + sbindir /sbin + libexecdir /libexec + libdir /lib +} { + define $name [opt-val $name $exec_prefix$defpath] +} +foreach {name defpath} { + datadir /share + sysconfdir /etc + sharedstatedir /com + localstatedir /var + infodir /share/info + mandir /share/man + includedir /include +} { + define $name [opt-val $name $prefix$defpath] +} + +define SHELL [get-env SHELL [find-an-executable sh bash ksh]] + +# Windows vs. non-Windows +switch -glob -- [get-define host] { + *-*-ming* - *-*-cygwin { + define-feature windows + define EXEEXT .exe + } + default { + define EXEEXT "" + } +} + +# Display +msg-result "Host System...[get-define host]" +msg-result "Build System...[get-define build]" diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh new file mode 100755 index 0000000..75126d2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh @@ -0,0 +1,20 @@ +# A small Tcl script to verify that the chosen +# interpreter works. Sometimes we might e.g. pick up +# an interpreter for a different arch. +# Outputs the full path to the interpreter + +if {[catch {info version} version] == 0} { + # This is Jim Tcl + if {$version >= 0.72} { + # Ensure that regexp works + regexp (a.*?) a + puts [info nameofexecutable] + exit 0 + } +} elseif {[catch {info tclversion} version] == 0} { + if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} { + puts [info nameofexecutable] + exit 0 + } +} +exit 1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl new file mode 100755 index 0000000..e7adf4b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl @@ -0,0 +1,3 @@ +# No need for package support in the bootstrap jimsh, but +# Tcl extensions call package require +proc package {args} {} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/configure b/android/external/usb_modeswitch/usb_modeswitch/jim/configure new file mode 100755 index 0000000..1c5586f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/configure @@ -0,0 +1,3 @@ +#!/bin/sh +dir="`dirname "$0"`/autosetup" +WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/configure.ac b/android/external/usb_modeswitch/usb_modeswitch/jim/configure.ac new file mode 100755 index 0000000..b70b5d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/configure.ac @@ -0,0 +1 @@ +# Dummy configure.ac to make automake happy diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt new file mode 100755 index 0000000..8dbfcfc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt @@ -0,0 +1,65 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs86142ang; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Received: by 10.142.238.12 with SMTP id l12mr5009290wfh.204.1216194359186; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Return-Path: <andrew@lunn.ch> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 31si6762736wff.16.2008.07.16.00.45.57; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Received-SPF: fail (google.com: domain of andrew@lunn.ch does not designate 209.85.100.29 as permitted sender) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=hardfail (google.com: domain of andrew@lunn.ch does not designate 209.85.100.29 as permitted sender) smtp.mail=andrew@lunn.ch +Received: from londo.lunn.ch ([80.238.139.98]:48839 ident=mail) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <andrew@lunn.ch>) + id 1KJ1ht-00085G-Ng + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 09:45:52 +0200 +Received: from lunn by londo.lunn.ch with local (Exim 3.36 #1 (Debian)) + id 1KJ1hq-0005ss-00; Wed, 16 Jul 2008 09:45:46 +0200 +Date: Wed, 16 Jul 2008 09:45:46 +0200 +From: Andrew Lunn <andrew@lunn.ch> +To: ?yvind Harboe <oyvind.harboe@zylin.com> +Cc: jim-devel@lists.berlios.de, antirez@gmail.com, patthoyts@users.sf.net, + andrew@lunn.ch, openocd@duaneellis.com, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +Subject: Re: Change Jim Tcl license +Message-ID: <20080716074546.GC24771@lunn.ch> +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - lunn.ch +X-Source: +X-Source-Args: +X-Source-Dir: + +On Wed, Jul 16, 2008 at 09:34:14AM +0200, ?yvind Harboe wrote: +> Hi all, +> +> I'm currently the maintainer of Jim Tcl trying as best as I can +> to fill Salvatore's shoes. +> +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. + +I've no problems with this, but my contributions are very minimal. + +Do you want this written down, in blood, to keep the lawyers happy? + +At a minimum i think everybody's agreement needs to be posted to a +public email list which is publicly archived etc so there is a +record of the agreement... + + Andrew diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt new file mode 100755 index 0000000..806f7ed --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt @@ -0,0 +1,87 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs114742ang; + Wed, 16 Jul 2008 08:58:18 -0700 (PDT) +Received: by 10.114.137.2 with SMTP id k2mr325372wad.95.1216223896673; + Wed, 16 Jul 2008 08:58:16 -0700 (PDT) +Return-Path: <ml-jim@qiao.in-berlin.de> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id m28si10145125waf.16.2008.07.16.08.58.15; + Wed, 16 Jul 2008 08:58:16 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of ml-jim@qiao.in-berlin.de) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of ml-jim@qiao.in-berlin.de) smtp.mail=ml-jim@qiao.in-berlin.de +Received: from gnu.in-berlin.de ([192.109.42.4]:58401) + by cpanel5.proisp.no with esmtps (TLSv1:AES256-SHA:256) + (Exim 4.69) + (envelope-from <ml-jim@qiao.in-berlin.de>) + id 1KJ9OG-0006Hf-8y + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 17:58:07 +0200 +X-Envelope-From: ml-jim@qiao.in-berlin.de +X-Envelope-To: <oyvind.harboe@zylin.com> +Received: from qiao.in-berlin.de (qiao.in-berlin.de [217.197.85.72]) + by gnu.in-berlin.de (8.13.8/8.13.8/Debian-2) with ESMTP id m6GFvxio009504 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 17:58:02 +0200 +Received: from [192.168.0.10] ([::ffff:192.168.0.10]) + by qiao.in-berlin.de with esmtp; Wed, 16 Jul 2008 18:00:04 +0200 + id 0001D68D.487E1B04.000042E7 +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Mime-Version: 1.0 (Apple Message framework v753.1) +Content-Type: text/plain; charset=ISO-8859-1; delsp=yes; format=flowed +Message-Id: <E112D7A6-89D1-40C8-913C-7DAF7303E7EC@qiao.in-berlin.de> +Cc: jim-devel@lists.berlios.de, antirez@gmail.com, patthoyts@users.sf.net, + andrew@lunn.ch, openocd@duaneellis.com, uklein@klein-messgeraete.de +Content-Transfer-Encoding: quoted-printable +From: Clemens Hintze <ml-jim@qiao.in-berlin.de> +Subject: Re: Change Jim Tcl license +Date: Wed, 16 Jul 2008 17:58:14 +0200 +To: "=?ISO-8859-1?Q?\"=D8yvind_Harboe\"?=" <oyvind.harboe@zylin.com> +X-Mailer: Apple Mail (2.753.1) +X-Spam-Score: (0.101) BAYES_50,RDNS_NONE +X-Scanned-By: MIMEDefang_at_IN-Berlin_e.V. on 192.109.42.4 +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - qiao.in-berlin.de +X-Source: +X-Source-Args: +X-Source-Dir: + + +Am 16.07.2008 um 09:34 schrieb =D8yvind Harboe: + +> Hi all, + +Hi =D8yvind, + +(...) + +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. + +No problem with me: I agree to permit my contributions to the Jim =20 +project to be +re-licensed under a BSD compatible license. + +(...) + +> Please let me know if any of the emails below are wrong(chi is +> missing) or the list is not complete. + +After consultation with the voices in my head, I can ensure you, =20 +'chi' is also agreeing with the re-licensing, because its me too ;-) + +Thank you very much to revive Jim! :-) + +Best regards, +Clemens Hintze. + +(...)= diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt new file mode 100755 index 0000000..56f962c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt @@ -0,0 +1,65 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs93801ang; + Wed, 16 Jul 2008 03:40:02 -0700 (PDT) +Received: by 10.142.148.10 with SMTP id v10mr5070849wfd.317.1216204801306; + Wed, 16 Jul 2008 03:40:01 -0700 (PDT) +Return-Path: <openocd@duaneellis.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 27si9313433wff.3.2008.07.16.03.40.00; + Wed, 16 Jul 2008 03:40:01 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of openocd@duaneellis.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of openocd@duaneellis.com) smtp.mail=openocd@duaneellis.com +Received: from smtpout10-04.prod.mesa1.secureserver.net ([64.202.165.238]:48803 helo=smtpout10.prod.mesa1.secureserver.net) + by cpanel5.proisp.no with smtp (Exim 4.69) + (envelope-from <openocd@duaneellis.com>) + id 1KJ4QL-0005cq-GB + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 12:39:54 +0200 +Received: (qmail 2305 invoked from network); 16 Jul 2008 10:39:56 -0000 +Received: from unknown (68.37.53.103) + by smtpout10-04.prod.mesa1.secureserver.net (64.202.165.238) with ESMTP; 16 Jul 2008 10:39:55 -0000 +Message-ID: <487DCFEC.4010104@duaneellis.com> +Date: Wed, 16 Jul 2008 06:39:40 -0400 +From: Duane Ellis <openocd@duaneellis.com> +Reply-To: openocd@duaneellis.com +User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) +MIME-Version: 1.0 +To: =?ISO-8859-1?Q?=D8yvind_Harboe?= <oyvind.harboe@zylin.com> +CC: jim-devel@lists.berlios.de, antirez@gmail.com, + patthoyts@users.sf.net, andrew@lunn.ch, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +Subject: Re: Change Jim Tcl license +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 8bit +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - duaneellis.com +X-Source: +X-Source-Args: +X-Source-Dir: + +Oyvind Harboe wrote: +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. +> +> +OK - from me + + --Duane. + +-Duane. + + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt new file mode 100755 index 0000000..af4a8e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt @@ -0,0 +1,85 @@ + +Received: by 10.100.7.20 with HTTP; Wed, 16 Jul 2008 10:12:05 -0700 (PDT) +Message-ID: <c09652430807161012m178c5fbesef9a3f831e4d1dac@mail.gmail.com> +Date: Wed, 16 Jul 2008 19:12:05 +0200 +From: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Sender: oyvindharboe@gmail.com +To: jim-devel@lists.berlios.de +Subject: Re: Change Jim Tcl license +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Delivered-To: oyvindharboe@gmail.com +X-Google-Sender-Auth: fc18e85532eee8f2 + +For the record: + +I would like my contributions to Jim Tcl to be under a FreeBSD license too= +. + +On Wed, Jul 16, 2008 at 9:34 AM, =D8yvind Harboe <oyvind.harboe@zylin.com> = +wrote: +> Hi all, +> +> I'm currently the maintainer of Jim Tcl trying as best as I can +> to fill Salvatore's shoes. +> +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. +> +> Long story: +> +> The current Jim Tcl license has a problem with GPL. If you +> link GPL code and Jim Tcl, the result is no license at all. +> +> This prevents Jim Tcl from being used in GPL projects. +> +> Lately Jim Tcl has been used with OpenOCD, a GPL project, +> and the license issue must be resolved one way or another. +> +> Upon conferring with Jonathan Larmour <jifl@ecoscentric.com>, who +> has kindly helped out with his knowledge on the topic, I have +> concluded that the best way to rectify this is to change the +> Jim Tcl license to a FreeBSD license. See OpenOCD mailing +> list for a discussion on this if you want details. +> +> http://www.fsf.org/licensing/licenses/index_html#FreeBSD +> +> As far as I can determine, below is the complete list of contributors. +> +> +> antirez - Salvatore Sanfilippo <antirez@gmail.com> +> patthoyts - ?? Pat Thoyts <patthoyts@users.sf.net> +> oharboe - =D8yvind Harboe - soyvind.harboe@zylin.com +> chi - ?? +> Andrew Lunn <andrew@lunn.ch> +> Duane Ellis <openocd@duaneellis.com> +> Uwe Klein <uklein@klein-messgeraete.de> +> Clemens Hintze ml-jim@qiao.in-berlin.de +> +> Please let me know if any of the emails below are wrong(chi is +> missing) or the list is not complete. +> +> +> -- +> =D8yvind Harboe +> http://www.zylin.com/zy1000.html +> ARM7 ARM9 XScale Cortex +> JTAG debugger and flash programmer +> + + + +--=20 +=D8yvind Harboe +http://www.zylin.com/zy1000.html +ARM7 ARM9 XScale Cortex +JTAG debugger and flash programmer diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt new file mode 100755 index 0000000..988a599 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt @@ -0,0 +1,84 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs108097ang; + Wed, 16 Jul 2008 07:49:02 -0700 (PDT) +Received: by 10.142.232.20 with SMTP id e20mr80874wfh.138.1216219741865; + Wed, 16 Jul 2008 07:49:01 -0700 (PDT) +Return-Path: <patthoyts@users.sourceforge.net> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 30si10551683wff.18.2008.07.16.07.49.01; + Wed, 16 Jul 2008 07:49:01 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of patthoyts@users.sourceforge.net) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of patthoyts@users.sourceforge.net) smtp.mail=patthoyts@users.sourceforge.net +Received: from smtp-out4.blueyonder.co.uk ([195.188.213.7]:38596) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <patthoyts@users.sourceforge.net>) + id 1KJ8JH-0000Vd-OT + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 16:48:52 +0200 +Received: from [172.23.170.141] (helo=anti-virus02-08) + by smtp-out4.blueyonder.co.uk with smtp (Exim 4.52) + id 1KJ8JO-0007r0-Cy; Wed, 16 Jul 2008 15:48:58 +0100 +Received: from [77.102.249.21] (helo=badger.patthoyts.tk) + by asmtp-out4.blueyonder.co.uk with esmtp (Exim 4.52) + id 1KJ8J6-0000gY-VY; Wed, 16 Jul 2008 15:48:41 +0100 +Received: by badger.patthoyts.tk (Postfix, from userid 1000) + id 810535184F; Wed, 16 Jul 2008 15:48:40 +0100 (BST) +Sender: pat@badger.patthoyts.tk +To: =?iso-8859-1?q?=D8yvind_Harboe?= <oyvind.harboe@zylin.com> +Cc: jim-devel@lists.berlios.de +Subject: Re: Change Jim Tcl license +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Face: .`d#euqz@6H{";Ysmx2IVe_7M3vA+2w1X[QLk?ZO&QRauXQL{*L'$3getx}9+zK.-KWDx3. + qrlR)76MFb`6bgoGvLpLtcQKB=X~;*<JKLtwLBM(IA'?rVjs1*tq\VHn?WMNsB,3XXWF@5.)4SRFa+ + '?a?.s#@hl7CiTo'F"O!fvbL0 +X-Url: http://www.patthoyts.tk/ +From: Pat Thoyts <patthoyts@users.sourceforge.net> +Date: 16 Jul 2008 15:48:39 +0100 +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Message-ID: <87fxq97um0.fsf@badger.patthoyts.tk> +Lines: 27 +User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - users.sourceforge.net +X-Source: +X-Source-Args: +X-Source-Dir: + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +"=D8yvind Harboe" <oyvind.harboe@zylin.com> writes: + +>If you have contributed to Jim Tcl, please reply to this email +>that you agree that we can switch Jim Tcl to a FreeBSD license. +> +>Once I have a record of all contributors agreeing to switch +>to a FreeBSD license, I'll update CVS. + +I hereby agree to permit my contributions to the Jim project to be +re-licensed under a BSD compatible license. + +- --=20 +Pat Thoyts http://www.patthoyts.tk/ +PGP fingerprint 2C 6E 98 07 2C 59 C8 97 10 CE 11 E6 04 E0 B9 DD +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.8 (SunOS) +Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/> + +iQCVAwUBSH4KO2B90JXwhOSJAQKtqQP9ERwSXpbP69l4JSrunG29Rhu2F3r83zu3 +GAKpFu4HwkVnIStLQ4o3tsqG9uKrVDbRMa187eSwHmlXXIMwDlkCKNsDFxvdLDZz +kbTYDibspYSw6CjwOUSTXifK9P7ho4Q7PtsRnJ8T1IMlGJlwg39Rxd+mpEO/if3q +ExIwM1aBbAs=3D +=3Du8si +-----END PGP SIGNATURE----- + diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt new file mode 100755 index 0000000..5bbf973 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt @@ -0,0 +1,88 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs113143ang; + Wed, 16 Jul 2008 08:41:11 -0700 (PDT) +Received: by 10.142.140.15 with SMTP id n15mr127048wfd.84.1216222870242; + Wed, 16 Jul 2008 08:41:10 -0700 (PDT) +Return-Path: <antirez@gmail.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 29si7397124wfg.0.2008.07.16.08.41.08; + Wed, 16 Jul 2008 08:41:10 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of antirez@gmail.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of antirez@gmail.com) smtp.mail=antirez@gmail.com; dkim=pass (test mode) header.i=@gmail.com +Received: from fg-out-1718.google.com ([72.14.220.155]:16058) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <antirez@gmail.com>) + id 1KJ97g-0004yX-1W + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 17:40:59 +0200 +Received: by fg-out-1718.google.com with SMTP id l27so3985052fgb.19 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 08:40:59 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=domainkey-signature:received:received:message-id:date:from:to + :subject:cc:in-reply-to:mime-version:content-type + :content-transfer-encoding:content-disposition:references; + bh=/aWDZQfgMBPqomYWZ2AUKOhhGMju+bwnSBbKL8MBonA=; + b=i0P3OKDopn/vHfa5ZrUvBjuPBnj43GMw8FOXKjxM/IfvywJParYqBS2Vmlw8RTndFg + J5wwxXf5056cZu/GbKbj8xLfylFfSInVaO7OnDutA3CeX1iU35my1DU6l9W6ILkLiT1P + Azi3L27rFQrzau/s53VU/UVELc3WckWdu1a1k= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=gmail.com; s=gamma; + h=message-id:date:from:to:subject:cc:in-reply-to:mime-version + :content-type:content-transfer-encoding:content-disposition + :references; + b=ww2MIz9svJttgS8mTRBhEX8Isveugn2hl3sMcgh0hZ1+ln8YbiysxYxZkdddewWm02 + WXsWgSgwy7MIPAUK1tNjzgkZ2l789SdrAtBCmqmRWJJI+ESTqbHMz8cqW+QRVP/A9Dfm + 8+AR85DHi7SOB0mdHtq9fsavZReUdaSIgy6F4= +Received: by 10.86.80.5 with SMTP id d5mr2284433fgb.19.1216222858224; + Wed, 16 Jul 2008 08:40:58 -0700 (PDT) +Received: by 10.86.50.18 with HTTP; Wed, 16 Jul 2008 08:40:58 -0700 (PDT) +Message-ID: <c6114db60807160840n62186f46w7cdc1bbec91186ca@mail.gmail.com> +Date: Wed, 16 Jul 2008 17:40:58 +0200 +From: "Salvatore Sanfilippo" <antirez@gmail.com> +To: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Subject: Re: Change Jim Tcl license +Cc: jim-devel@lists.berlios.de, patthoyts@users.sf.net, andrew@lunn.ch, + openocd@duaneellis.com, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - gmail.com +X-Source: +X-Source-Args: +X-Source-Dir: + +I agree to permit my contributions to the Jim project to be +re-licensed under a BSD compatible license. + +Since I'm currently the top contributor if it's safer from +the legal point of view I can also put a tar.gz of the current +Jim source code with a BSD "LICENSE" file on my website. + +Otherwise I can sign by hand a letter and send a digitalized +image here. + +Ciao, +Salvatore + +-- +Salvatore 'antirez' Sanfilippo +http://antirez.com + +Organizations which design systems are constrained to produce designs +which are copies of the communication structures of these +organizations. + +Conway's Law diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt new file mode 100755 index 0000000..035ca32 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt @@ -0,0 +1,73 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs89014ang; + Wed, 16 Jul 2008 01:58:32 -0700 (PDT) +Received: by 10.142.125.9 with SMTP id x9mr5028534wfc.123.1216198711465; + Wed, 16 Jul 2008 01:58:31 -0700 (PDT) +Return-Path: <wiederling@googlemail.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 30si6756166wfa.10.2008.07.16.01.58.29; + Wed, 16 Jul 2008 01:58:31 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of wiederling@googlemail.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of wiederling@googlemail.com) smtp.mail=wiederling@googlemail.com; dkim=pass (test mode) header.i=@googlemail.com +Received: from wr-out-0506.google.com ([64.233.184.233]:51225) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <wiederling@googlemail.com>) + id 1KJ2q7-00057b-IR + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 10:58:24 +0200 +Received: by wr-out-0506.google.com with SMTP id c8so2209154wra.27 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=googlemail.com; s=gamma; + h=domainkey-signature:received:received:message-id:date:from:to + :subject:cc:in-reply-to:mime-version:content-type + :content-transfer-encoding:content-disposition:references; + bh=VxcH0g2H5iLUo27gqJiqrlY4uVbN1NFE4skyMKqysPM=; + b=JPK53r6LQ6GqBCG1kfVYyTPuPuVhlBrbzQ8oSBwpwuwwB7t3CSv+c75jRjb/n3y8mi + gN1r6noZucK9ZpRZiHxYZpHVhYFcWbZ+ZXM75H2qIFfl4YDzfgg/Ub7CzoR2LskuBsRk + DMH2LnyAYf+Om2YAKJdkoMnGbPMDMFSrNHeIc= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=googlemail.com; s=gamma; + h=message-id:date:from:to:subject:cc:in-reply-to:mime-version + :content-type:content-transfer-encoding:content-disposition + :references; + b=VAGlxpb1YGbex/eaS0tQgWvH/lWHzgD5R/rxjshVSwZJOStwqMA1F5jNQgybQFIn1F + zWoiAV81uWMzBEGYab7SGsStWLxovcBSgi9NL+XqwAkhBdrWjgFPvpBHn5PvgOOXEhGH + EGhjrY8qp2LSxhFcW3/DvgObhBBKtY1J+qzvA= +Received: by 10.90.115.17 with SMTP id n17mr1231758agc.90.1216198705850; + Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +Received: by 10.90.105.18 with HTTP; Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +Message-ID: <1af31b6f0807160158o295303adh43abdd34fbe8ec99@mail.gmail.com> +Date: Wed, 16 Jul 2008 10:58:25 +0200 +From: "Uwe Klein" <wiederling@googlemail.com> +To: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Subject: Re: [Jim-devel] Change Jim Tcl license +Cc: jim-devel@lists.berlios.de, patthoyts@users.sf.net, andrew@lunn.ch, + uklein@klein-messgeraete.de, antirez@gmail.com, + openocd@duaneellis.com, ml-jim@qiao.in-berlin.de +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - googlemail.com +X-Source: +X-Source-Args: +X-Source-Dir: + +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. + +For Uwe Klein <uklein@klein-messgeraete.de> + +This is OK with me. + +uwe diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/glob.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/glob.tcl new file mode 100755 index 0000000..cd94d8d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/glob.tcl @@ -0,0 +1,129 @@ +# Implements a Tcl-compatible glob command based on readdir +# +# (c) 2008 Steve Bennett <steveb@workware.net.au> +# +# See LICENCE in this directory for licensing. + +package require readdir + +# Implements the Tcl glob command +# +# Usage: glob ?-nocomplain? pattern ... +# +# Patterns use 'string match' (glob) pattern matching for each +# directory level, plus support for braced alternations. +# +# e.g. glob "te[a-e]*/*.{c,tcl}" +# +# Note: files starting with . will only be returned if matching component +# of the pattern starts with . +proc glob {args} { + + # If $dir is a directory, return a list of all entries + # it contains which match $pattern + # + local proc glob.readdir_pattern {dir pattern} { + set result {} + + # readdir doesn't return . or .., so simulate it here + if {$pattern in {. ..}} { + return $pattern + } + + # If the pattern isn't actually a pattern... + if {[string match {*[*?]*} $pattern]} { + # Use -nocomplain here to return nothing if $dir is not a directory + set files [readdir -nocomplain $dir] + } elseif {[file isdir $dir] && [file exists $dir/$pattern]} { + set files [list $pattern] + } else { + set files "" + } + + foreach name $files { + if {[string match $pattern $name]} { + # Only include entries starting with . if the pattern starts with . + if {[string index $name 0] eq "." && [string index $pattern 0] ne "."} { + continue + } + lappend result $name + } + } + + return $result + } + + # If the pattern contains a braced expression, return a list of + # patterns with the braces expanded. {c,b}* => c* b* + # Otherwise just return the pattern + # Note: Only supports one braced expression. i.e. not {a,b}*{c,d}* + proc glob.expandbraces {pattern} { + # Avoid regexp for dependency reasons. + # XXX: Doesn't handle backslashed braces + if {[set fb [string first "\{" $pattern]] < 0} { + return $pattern + } + if {[set nb [string first "\}" $pattern $fb]] < 0} { + return $pattern + } + set before [string range $pattern 0 $fb-1] + set braced [string range $pattern $fb+1 $nb-1] + set after [string range $pattern $nb+1 end] + + lmap part [split $braced ,] { + set pat $before$part$after + } + } + + # Core glob implementation. Returns a list of files/directories matching the pattern + proc glob.glob {pattern} { + set dir [file dirname $pattern] + if {$dir eq $pattern} { + # At the top level + return [list $dir] + } + + # Recursively expand the parent directory + set dirlist [glob.glob $dir] + set pattern [file tail $pattern] + + # Now collect the fiels/directories + set result {} + foreach dir $dirlist { + set globdir $dir + if {[string match "*/" $dir]} { + set sep "" + } elseif {$dir eq "."} { + set globdir "" + set sep "" + } else { + set sep / + } + foreach pat [glob.expandbraces $pattern] { + foreach name [glob.readdir_pattern $dir $pat] { + lappend result $globdir$sep$name + } + } + } + return $result + } + + # Start of main glob + set nocomplain 0 + + if {[lindex $args 0] eq "-nocomplain"} { + set nocomplain 1 + set args [lrange $args 1 end] + } + + set result {} + foreach pattern $args { + lappend result {*}[glob.glob $pattern] + } + + if {$nocomplain == 0 && [llength $result] == 0} { + return -code error "no files matched glob patterns" + } + + return $result +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl new file mode 100755 index 0000000..a764f3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl @@ -0,0 +1,27 @@ +# This pseudo-package is loaded from jimsh to add additional +# paths to $auto_path and to source ~/.jimrc + +proc _jimsh_init {} { + rename _jimsh_init {} + + # Add to the standard auto_path + lappend p {*}[split [env JIMLIB {}] $::tcl_platform(pathSeparator)] + lappend p {*}$::auto_path + lappend p [file dirname [info nameofexecutable]] + set ::auto_path $p + + if {$::tcl_interactive && [env HOME {}] ne ""} { + foreach src {.jimrc jimrc.tcl} { + if {[file exists [env HOME]/$src]} { + uplevel #0 source [env HOME]/$src + break + } + } + } +} + +if {$tcl_platform(platform) eq "windows"} { + set jim_argv0 [string map {\\ /} $jim_argv0] +} + +_jimsh_init diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-aio.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-aio.c new file mode 100755 index 0000000..710a47d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-aio.c @@ -0,0 +1,1353 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#include "jim.h" +#include "jimautoconf.h" + +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#else +#define JIM_ANSIC +#endif + +#include "jim-eventloop.h" +#include "jim-subcmd.h" + +#define AIO_CMD_LEN 32 /* e.g. aio.handleXXXXXX */ +#define AIO_BUF_LEN 256 /* Can keep this small and rely on stdio buffering */ + +#define AIO_KEEPOPEN 1 + +#if defined(JIM_IPV6) +#define IPV6 1 +#else +#define IPV6 0 +#ifndef PF_INET6 +#define PF_INET6 0 +#endif +#endif + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +union sockaddr_any { + struct sockaddr sa; + struct sockaddr_in sin; +#if IPV6 + struct sockaddr_in6 sin6; +#endif +}; + +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, int size) +{ + if (af != PF_INET) { + return NULL; + } + snprintf(dst, size, "%s", inet_ntoa(((struct sockaddr_in *)src)->sin_addr)); + return dst; +} +#endif +#endif /* JIM_BOOTSTRAP */ + +typedef struct AioFile +{ + FILE *fp; + Jim_Obj *filename; + int type; + int OpenFlags; /* AIO_KEEPOPEN? keep FILE* */ + int fd; +#ifdef O_NDELAY + int flags; +#endif + Jim_Obj *rEvent; + Jim_Obj *wEvent; + Jim_Obj *eEvent; + int addr_family; +} AioFile; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode); + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +static int JimParseIPv6Address(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen) +{ +#if IPV6 + /* + * An IPv6 addr/port looks like: + * [::1] + * [::1]:2000 + * [fe80::223:6cff:fe95:bdc0%en1]:2000 + * [::]:2000 + * 2000 + * + * Note that the "any" address is ::, which is the same as when no address is specified. + */ + char *sthost = NULL; + const char *stport; + int ret = JIM_OK; + struct addrinfo req; + struct addrinfo *ai; + + stport = strrchr(hostport, ':'); + if (!stport) { + /* No : so, the whole thing is the port */ + stport = hostport; + hostport = "::"; + sthost = Jim_StrDup(hostport); + } + else { + stport++; + } + + if (*hostport == '[') { + /* This is a numeric ipv6 address */ + char *pt = strchr(++hostport, ']'); + if (pt) { + sthost = Jim_StrDupLen(hostport, pt - hostport); + } + } + + if (!sthost) { + sthost = Jim_StrDupLen(hostport, stport - hostport - 1); + } + + memset(&req, '\0', sizeof(req)); + req.ai_family = PF_INET6; + + if (getaddrinfo(sthost, NULL, &req, &ai)) { + Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport); + ret = JIM_ERR; + } + else { + memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen); + *salen = ai->ai_addrlen; + + sa->sin.sin_port = htons(atoi(stport)); + + freeaddrinfo(ai); + } + Jim_Free(sthost); + + return ret; +#else + Jim_SetResultString(interp, "ipv6 not supported", -1); + return JIM_ERR; +#endif +} + +static int JimParseIpAddress(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen) +{ + /* An IPv4 addr/port looks like: + * 192.168.1.5 + * 192.168.1.5:2000 + * 2000 + * + * If the address is missing, INADDR_ANY is used. + * If the port is missing, 0 is used (only useful for server sockets). + */ + char *sthost = NULL; + const char *stport; + int ret = JIM_OK; + + stport = strrchr(hostport, ':'); + if (!stport) { + /* No : so, the whole thing is the port */ + stport = hostport; + sthost = Jim_StrDup("0.0.0.0"); + } + else { + sthost = Jim_StrDupLen(hostport, stport - hostport); + stport++; + } + + { +#ifdef HAVE_GETADDRINFO + struct addrinfo req; + struct addrinfo *ai; + memset(&req, '\0', sizeof(req)); + req.ai_family = PF_INET; + + if (getaddrinfo(sthost, NULL, &req, &ai)) { + ret = JIM_ERR; + } + else { + memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen); + *salen = ai->ai_addrlen; + freeaddrinfo(ai); + } +#else + struct hostent *he; + + ret = JIM_ERR; + + if ((he = gethostbyname(sthost)) != NULL) { + if (he->h_length == sizeof(sa->sin.sin_addr)) { + *salen = sizeof(sa->sin); + sa->sin.sin_family= he->h_addrtype; + memcpy(&sa->sin.sin_addr, he->h_addr, he->h_length); /* set address */ + ret = JIM_OK; + } + } +#endif + + sa->sin.sin_port = htons(atoi(stport)); + } + Jim_Free(sthost); + + if (ret != JIM_OK) { + Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport); + } + + return ret; +} + +#ifdef HAVE_SYS_UN_H +static int JimParseDomainAddress(Jim_Interp *interp, const char *path, struct sockaddr_un *sa) +{ + sa->sun_family = PF_UNIX; + snprintf(sa->sun_path, sizeof(sa->sun_path), "%s", path); + + return JIM_OK; +} +#endif +#endif /* JIM_BOOTSTRAP */ + +static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name) +{ + if (name) { + Jim_SetResultFormatted(interp, "%#s: %s", name, strerror(errno)); + } + else { + Jim_SetResultString(interp, strerror(errno), -1); + } +} + +static void JimAioDelProc(Jim_Interp *interp, void *privData) +{ + AioFile *af = privData; + + JIM_NOTUSED(interp); + + Jim_DecrRefCount(interp, af->filename); + + if (!(af->OpenFlags & AIO_KEEPOPEN)) { + fclose(af->fp); + } +#ifdef jim_ext_eventloop + /* remove existing EventHandlers */ + if (af->rEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } + if (af->wEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } + if (af->eEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } +#endif + Jim_Free(af); +} + +static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int nonewline = 0; + int neededLen = -1; /* -1 is "read as much as possible" */ + + if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + nonewline = 1; + argv++; + argc--; + } + if (argc == 1) { + jim_wide wideValue; + + if (Jim_GetWide(interp, argv[0], &wideValue) != JIM_OK) + return JIM_ERR; + if (wideValue < 0) { + Jim_SetResultString(interp, "invalid parameter: negative len", -1); + return JIM_ERR; + } + neededLen = (int)wideValue; + } + else if (argc) { + return -1; + } + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (neededLen != 0) { + int retval; + int readlen; + + if (neededLen == -1) { + readlen = AIO_BUF_LEN; + } + else { + readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); + } + retval = fread(buf, 1, readlen, af->fp); + if (retval > 0) { + Jim_AppendString(interp, objPtr, buf, retval); + if (neededLen != -1) { + neededLen -= retval; + } + } + if (retval != readlen) + break; + } + /* Check for error conditions */ + if (ferror(af->fp)) { + clearerr(af->fp); + /* eof and EAGAIN are not error conditions */ + if (!feof(af->fp) && errno != EAGAIN) { + /* I/O error */ + Jim_FreeNewObj(interp, objPtr); + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + } + if (nonewline) { + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + long count = 0; + long maxlen = LONG_MAX; + FILE *outfh = Jim_AioFilehandle(interp, argv[0]); + + if (outfh == NULL) { + return JIM_ERR; + } + + if (argc == 2) { + if (Jim_GetLong(interp, argv[1], &maxlen) != JIM_OK) { + return JIM_ERR; + } + } + + while (count < maxlen) { + int ch = fgetc(af->fp); + + if (ch == EOF || fputc(ch, outfh) == EOF) { + break; + } + count++; + } + + if (ferror(af->fp)) { + Jim_SetResultFormatted(interp, "error while reading: %s", strerror(errno)); + clearerr(af->fp); + return JIM_ERR; + } + + if (ferror(outfh)) { + Jim_SetResultFormatted(interp, "error while writing: %s", strerror(errno)); + clearerr(outfh); + return JIM_ERR; + } + + Jim_SetResultInt(interp, count); + + return JIM_OK; +} + +static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int len; + + errno = 0; + + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (1) { + buf[AIO_BUF_LEN - 1] = '_'; + if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL) + break; + + if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') { + Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1); + } + else { + len = strlen(buf); + + if (len && (buf[len - 1] == '\n')) { + /* strip "\n" */ + len--; + } + + Jim_AppendString(interp, objPtr, buf, len); + break; + } + } + if (ferror(af->fp) && errno != EAGAIN && errno != EINTR) { + /* I/O error */ + Jim_FreeNewObj(interp, objPtr); + JimAioSetError(interp, af->filename); + clearerr(af->fp); + return JIM_ERR; + } + + if (argc) { + if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + return JIM_ERR; + } + + len = Jim_Length(objPtr); + + if (len == 0 && feof(af->fp)) { + /* On EOF returns -1 if varName was specified */ + len = -1; + } + Jim_SetResultInt(interp, len); + } + else { + Jim_SetResult(interp, objPtr); + } + return JIM_OK; +} + +static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int wlen; + const char *wdata; + Jim_Obj *strObj; + + if (argc == 2) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + return -1; + } + strObj = argv[1]; + } + else { + strObj = argv[0]; + } + + wdata = Jim_GetString(strObj, &wlen); + if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) { + if (argc == 2 || putc('\n', af->fp) != EOF) { + return JIM_OK; + } + } + JimAioSetError(interp, af->filename); + return JIM_ERR; +} + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char *buf; + union sockaddr_any sa; + long len; + socklen_t salen = sizeof(sa); + int rlen; + + if (Jim_GetLong(interp, argv[0], &len) != JIM_OK) { + return JIM_ERR; + } + + buf = Jim_Alloc(len + 1); + + rlen = recvfrom(fileno(af->fp), buf, len, 0, &sa.sa, &salen); + if (rlen < 0) { + Jim_Free(buf); + JimAioSetError(interp, NULL); + return JIM_ERR; + } + buf[rlen] = 0; + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, rlen)); + + if (argc > 1) { + /* INET6_ADDRSTRLEN is 46. Add some for [] and port */ + char addrbuf[60]; + +#if IPV6 + if (sa.sa.sa_family == PF_INET6) { + addrbuf[0] = '['; + /* Allow 9 for []:65535\0 */ + inet_ntop(sa.sa.sa_family, &sa.sin6.sin6_addr, addrbuf + 1, sizeof(addrbuf) - 9); + snprintf(addrbuf + strlen(addrbuf), 8, "]:%d", ntohs(sa.sin.sin_port)); + } + else +#endif + { + /* Allow 7 for :65535\0 */ + inet_ntop(sa.sa.sa_family, &sa.sin.sin_addr, addrbuf, sizeof(addrbuf) - 7); + snprintf(addrbuf + strlen(addrbuf), 7, ":%d", ntohs(sa.sin.sin_port)); + } + + if (Jim_SetVariable(interp, argv[1], Jim_NewStringObj(interp, addrbuf, -1)) != JIM_OK) { + return JIM_ERR; + } + } + + return JIM_OK; +} + + +static int aio_cmd_sendto(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int wlen; + int len; + const char *wdata; + union sockaddr_any sa; + const char *addr = Jim_String(argv[1]); + int salen; + + if (IPV6 && af->addr_family == PF_INET6) { + if (JimParseIPv6Address(interp, addr, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, addr, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + wdata = Jim_GetString(argv[0], &wlen); + + /* Note that we don't validate the socket type. Rely on sendto() failing if appropriate */ + len = sendto(fileno(af->fp), wdata, wlen, 0, &sa.sa, salen); + if (len < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + Jim_SetResultInt(interp, len); + return JIM_OK; +} + +static int aio_cmd_accept(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int sock; + union sockaddr_any sa; + socklen_t addrlen = sizeof(sa); + + sock = accept(af->fd, &sa.sa, &addrlen); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + /* Create the file command */ + return JimMakeChannel(interp, NULL, sock, Jim_NewStringObj(interp, "accept", -1), + "aio.sockstream%ld", af->addr_family, "r+"); +} + +static int aio_cmd_listen(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + long backlog; + + if (Jim_GetLong(interp, argv[0], &backlog) != JIM_OK) { + return JIM_ERR; + } + + if (listen(af->fd, backlog)) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + return JIM_OK; +} +#endif /* JIM_BOOTSTRAP */ + +static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + if (fflush(af->fp) == EOF) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, feof(af->fp)); + return JIM_OK; +} + +static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_DeleteCommand(interp, Jim_String(argv[0])); + return JIM_OK; +} + +static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int orig = SEEK_SET; + long offset; + + if (argc == 2) { + if (Jim_CompareStringImmediate(interp, argv[1], "start")) + orig = SEEK_SET; + else if (Jim_CompareStringImmediate(interp, argv[1], "current")) + orig = SEEK_CUR; + else if (Jim_CompareStringImmediate(interp, argv[1], "end")) + orig = SEEK_END; + else { + return -1; + } + } + if (Jim_GetLong(interp, argv[0], &offset) != JIM_OK) { + return JIM_ERR; + } + if (fseek(af->fp, offset, orig) == -1) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, ftell(af->fp)); + return JIM_OK; +} + +static int aio_cmd_filename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResult(interp, af->filename); + return JIM_OK; +} + +#ifdef O_NDELAY +static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + int fmode = af->flags; + + if (argc) { + long nb; + + if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { + return JIM_ERR; + } + if (nb) { + fmode |= O_NDELAY; + } + else { + fmode &= ~O_NDELAY; + } + fcntl(af->fd, F_SETFL, fmode); + af->flags = fmode; + } + Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); + return JIM_OK; +} +#endif + +static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + static const char * const options[] = { + "none", + "line", + "full", + NULL + }; + enum + { + OPT_NONE, + OPT_LINE, + OPT_FULL, + }; + int option; + + if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NONE: + setvbuf(af->fp, NULL, _IONBF, 0); + break; + case OPT_LINE: + setvbuf(af->fp, NULL, _IOLBF, BUFSIZ); + break; + case OPT_FULL: + setvbuf(af->fp, NULL, _IOFBF, BUFSIZ); + break; + } + return JIM_OK; +} + +#ifdef jim_ext_eventloop +static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_DecrRefCount(interp, objPtr); +} + +static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask) +{ + Jim_Obj *objPtr = clientData; + + return Jim_EvalObjBackground(interp, objPtr); +} + +static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, + int argc, Jim_Obj * const *argv) +{ + int scriptlen = 0; + + if (argc == 0) { + /* Return current script */ + if (*scriptHandlerObj) { + Jim_SetResult(interp, *scriptHandlerObj); + } + return JIM_OK; + } + + if (*scriptHandlerObj) { + /* Delete old handler */ + Jim_DeleteFileHandler(interp, af->fp); + *scriptHandlerObj = NULL; + } + + /* Now possibly add the new script(s) */ + Jim_GetString(argv[0], &scriptlen); + if (scriptlen == 0) { + /* Empty script, so done */ + return JIM_OK; + } + + /* A new script to add */ + Jim_IncrRefCount(argv[0]); + *scriptHandlerObj = argv[0]; + + Jim_CreateFileHandler(interp, af->fp, mask, + JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer); + + return JIM_OK; +} + +static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv); +} + +static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv); +} + +static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv); +} +#endif + +static const jim_subcmd_type aio_command_table[] = { + { .cmd = "read", + .args = "?-nonewline? ?len?", + .function = aio_cmd_read, + .minargs = 0, + .maxargs = 2, + .description = "Read and return bytes from the stream. To eof if no len." + }, + { .cmd = "copyto", + .args = "handle ?size?", + .function = aio_cmd_copy, + .minargs = 1, + .maxargs = 2, + .description = "Copy up to 'size' bytes to the given filehandle, or to eof if no size." + }, + { .cmd = "gets", + .args = "?var?", + .function = aio_cmd_gets, + .minargs = 0, + .maxargs = 1, + .description = "Read one line and return it or store it in the var" + }, + { .cmd = "puts", + .args = "?-nonewline? str", + .function = aio_cmd_puts, + .minargs = 1, + .maxargs = 2, + .description = "Write the string, with newline unless -nonewline" + }, +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) + { .cmd = "recvfrom", + .args = "len ?addrvar?", + .function = aio_cmd_recvfrom, + .minargs = 1, + .maxargs = 2, + .description = "Receive up to 'len' bytes on the socket. Sets 'addrvar' with receive address, if set" + }, + { .cmd = "sendto", + .args = "str address", + .function = aio_cmd_sendto, + .minargs = 2, + .maxargs = 2, + .description = "Send 'str' to the given address (dgram only)" + }, + { .cmd = "accept", + .function = aio_cmd_accept, + .description = "Server socket only: Accept a connection and return stream" + }, + { .cmd = "listen", + .args = "backlog", + .function = aio_cmd_listen, + .minargs = 1, + .maxargs = 1, + .description = "Set the listen backlog for server socket" + }, +#endif /* JIM_BOOTSTRAP */ + { .cmd = "flush", + .function = aio_cmd_flush, + .description = "Flush the stream" + }, + { .cmd = "eof", + .function = aio_cmd_eof, + .description = "Returns 1 if stream is at eof" + }, + { .cmd = "close", + .flags = JIM_MODFLAG_FULLARGV, + .function = aio_cmd_close, + .description = "Closes the stream" + }, + { .cmd = "seek", + .args = "offset ?start|current|end", + .function = aio_cmd_seek, + .minargs = 1, + .maxargs = 2, + .description = "Seeks in the stream (default 'current')" + }, + { .cmd = "tell", + .function = aio_cmd_tell, + .description = "Returns the current seek position" + }, + { .cmd = "filename", + .function = aio_cmd_filename, + .description = "Returns the original filename" + }, +#ifdef O_NDELAY + { .cmd = "ndelay", + .args = "?0|1?", + .function = aio_cmd_ndelay, + .minargs = 0, + .maxargs = 1, + .description = "Set O_NDELAY (if arg). Returns current/new setting." + }, +#endif + { .cmd = "buffering", + .args = "none|line|full", + .function = aio_cmd_buffering, + .minargs = 1, + .maxargs = 1, + .description = "Sets buffering" + }, +#ifdef jim_ext_eventloop + { .cmd = "readable", + .args = "?readable-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_readable, + .description = "Returns script, or invoke readable-script when readable, {} to remove", + }, + { .cmd = "writable", + .args = "?writable-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_writable, + .description = "Returns script, or invoke writable-script when writable, {} to remove", + }, + { .cmd = "onexception", + .args = "?exception-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_onexception, + .description = "Returns script, or invoke exception-script when oob data, {} to remove", + }, +#endif + { 0 } +}; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv); +} + +static int JimAioOpenCommand(Jim_Interp *interp, int argc, + Jim_Obj *const *argv) +{ + FILE *fp; + const char *hdlfmt; + const char *mode; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); + return JIM_ERR; + } + + mode = (argc == 3) ? Jim_String(argv[2]) : "r"; + hdlfmt = Jim_String(argv[1]); + if (Jim_CompareStringImmediate(interp, argv[1], "stdin")) { + fp = stdin; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "stdout")) { + fp = stdout; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "stderr")) { + fp = stderr; + } + else { + const char *filename = Jim_String(argv[1]); + + +#ifdef jim_ext_tclcompat + /* If the filename starts with '|', use popen instead */ + if (*filename == '|') { + Jim_Obj *evalObj[3]; + + evalObj[0] = Jim_NewStringObj(interp, "popen", -1); + evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); + evalObj[2] = Jim_NewStringObj(interp, mode, -1); + + return Jim_EvalObjVector(interp, 3, evalObj); + } +#endif + hdlfmt = "aio.handle%ld"; + fp = NULL; + } + + /* Create the file command */ + return JimMakeChannel(interp, fp, -1, argv[1], hdlfmt, 0, mode); +} + +/** + * Creates a channel for fh/fd/filename. + * + * If fh is not NULL, uses that as the channel (and set AIO_KEEPOPEN). + * Otherwise, if fd is >= 0, uses that as the chanel. + * Otherwise opens 'filename' with mode 'mode'. + * + * hdlfmt is a sprintf format for the filehandle. Anything with %ld at the end will do. + * mode is used for open or fdopen. + * + * Creates the command and sets the name as the current result. + */ +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode) +{ + AioFile *af; + char buf[AIO_CMD_LEN]; + int OpenFlags = 0; + + Jim_IncrRefCount(filename); + + if (fh == NULL) { + if (fd < 0) { + fh = fopen(Jim_String(filename), mode); + } + else { + fh = fdopen(fd, mode); + } + } + else { + OpenFlags = AIO_KEEPOPEN; + } + + if (fh == NULL) { + JimAioSetError(interp, filename); + close(fd); + Jim_DecrRefCount(interp, filename); + return JIM_ERR; + } + + /* Create the file command */ + af = Jim_Alloc(sizeof(*af)); + memset(af, 0, sizeof(*af)); + af->fp = fh; + af->fd = fileno(fh); + af->filename = filename; +#ifdef FD_CLOEXEC + if ((OpenFlags & AIO_KEEPOPEN) == 0) { + fcntl(af->fd, F_SETFD, FD_CLOEXEC); + af->OpenFlags = OpenFlags; + } +#endif +#ifdef O_NDELAY + af->flags = fcntl(af->fd, F_GETFL); +#endif + af->addr_family = family; + snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); + Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); + + Jim_SetResultString(interp, buf, -1); + + return JIM_OK; +} + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) + +static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *hdlfmt = "aio.unknown%ld"; + const char *socktypes[] = { + "unix", + "unix.server", + "dgram", + "dgram.server", + "stream", + "stream.server", + "pipe", + NULL + }; + enum + { + SOCK_UNIX, + SOCK_UNIX_SERVER, + SOCK_DGRAM_CLIENT, + SOCK_DGRAM_SERVER, + SOCK_STREAM_CLIENT, + SOCK_STREAM_SERVER, + SOCK_STREAM_PIPE, + SOCK_DGRAM6_CLIENT, + SOCK_DGRAM6_SERVER, + SOCK_STREAM6_CLIENT, + SOCK_STREAM6_SERVER, + }; + int socktype; + int sock; + const char *hostportarg = NULL; + int res; + int on = 1; + const char *mode = "r+"; + int family = PF_INET; + Jim_Obj *argv0 = argv[0]; + int ipv6 = 0; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-ipv6")) { + if (!IPV6) { + Jim_SetResultString(interp, "ipv6 not supported", -1); + return JIM_ERR; + } + ipv6 = 1; + family = PF_INET6; + } + argc -= ipv6; + argv += ipv6; + + if (argc < 2) { + wrongargs: + Jim_WrongNumArgs(interp, 1, &argv0, "?-ipv6? type ?address?"); + return JIM_ERR; + } + + if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + + Jim_SetEmptyResult(interp); + + hdlfmt = "aio.sock%ld"; + + if (argc > 2) { + hostportarg = Jim_String(argv[2]); + } + + switch (socktype) { + case SOCK_DGRAM_CLIENT: + if (argc == 2) { + /* No address, so an unconnected dgram socket */ + sock = socket(family, SOCK_DGRAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + break; + } + /* fall through */ + case SOCK_STREAM_CLIENT: + { + union sockaddr_any sa; + int salen; + + if (argc != 3) { + goto wrongargs; + } + + if (ipv6) { + if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + sock = socket(family, (socktype == SOCK_DGRAM_CLIENT) ? SOCK_DGRAM : SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + res = connect(sock, &sa.sa, salen); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + } + break; + + case SOCK_STREAM_SERVER: + case SOCK_DGRAM_SERVER: + { + union sockaddr_any sa; + int salen; + + if (argc != 3) { + goto wrongargs; + } + + if (ipv6) { + if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + sock = socket(family, (socktype == SOCK_DGRAM_SERVER) ? SOCK_DGRAM : SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + /* Enable address reuse */ + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); + + res = bind(sock, &sa.sa, salen); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + if (socktype == SOCK_STREAM_SERVER) { + res = listen(sock, 5); + if (res) { + JimAioSetError(interp, NULL); + close(sock); + return JIM_ERR; + } + } + hdlfmt = "aio.socksrv%ld"; + } + break; + +#ifdef HAVE_SYS_UN_H + case SOCK_UNIX: + { + struct sockaddr_un sa; + socklen_t len; + + if (argc != 3 || ipv6) { + goto wrongargs; + } + + if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { + JimAioSetError(interp, argv[2]); + return JIM_ERR; + } + family = PF_UNIX; + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); + res = connect(sock, (struct sockaddr *)&sa, len); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + hdlfmt = "aio.sockunix%ld"; + break; + } + + case SOCK_UNIX_SERVER: + { + struct sockaddr_un sa; + socklen_t len; + + if (argc != 3 || ipv6) { + goto wrongargs; + } + + if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { + JimAioSetError(interp, argv[2]); + return JIM_ERR; + } + family = PF_UNIX; + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); + res = bind(sock, (struct sockaddr *)&sa, len); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + res = listen(sock, 5); + if (res) { + JimAioSetError(interp, NULL); + close(sock); + return JIM_ERR; + } + hdlfmt = "aio.sockunixsrv%ld"; + break; + } +#endif + +#ifdef HAVE_PIPE + case SOCK_STREAM_PIPE: + { + int p[2]; + + if (argc != 2 || ipv6) { + goto wrongargs; + } + + if (pipe(p) < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + if (JimMakeChannel(interp, NULL, p[0], argv[1], "aio.pipe%ld", 0, "r") == JIM_OK) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + + if (JimMakeChannel(interp, NULL, p[1], argv[1], "aio.pipe%ld", 0, "w") == JIM_OK) { + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + /* Can only be here if fdopen() failed */ + close(p[0]); + close(p[1]); + JimAioSetError(interp, NULL); + return JIM_ERR; + } + break; +#endif + default: + Jim_SetResultString(interp, "Unsupported socket type", -1); + return JIM_ERR; + } + + return JimMakeChannel(interp, NULL, sock, argv[1], hdlfmt, family, mode); +} +#endif /* JIM_BOOTSTRAP */ + +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) +{ + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); + + if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { + return ((AioFile *) cmdPtr->u.native.privData)->fp; + } + Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); + return NULL; +} + +int Jim_aioInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); +#ifndef JIM_ANSIC + Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); +#endif + + /* Takeover stdin, stdout and stderr */ + Jim_EvalGlobal(interp, "open stdin; open stdout; open stderr"); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-array.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-array.c new file mode 100755 index 0000000..89a86f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-array.c @@ -0,0 +1,274 @@ + +/* + * Implements the array command for jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* Just a regular [info exists] */ + Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); + return JIM_OK; +} + +static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + int all = 0; + Jim_Obj *resultObj; + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (!objPtr) { + return JIM_OK; + } + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + all = 1; + } + + /* If it is a dictionary or list with an even number of elements, nothing else to do */ + if (all) { + if (Jim_IsDict(objPtr) || (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0)) { + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + if (all) { + /* Return the whole array */ + Jim_SetResult(interp, dictObj); + } + else { + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i + 1]); + } + } + + Jim_SetResult(interp, resultObj); + } + Jim_Free(dictValuesObj); + return JIM_OK; + +} + +static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (!objPtr) { + return JIM_OK; + } + + return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); +} + +static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr; + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + /* Unset the whole array */ + Jim_UnsetVariable(interp, argv[0], JIM_NONE); + return JIM_OK; + } + + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Create a new object with the values which don't match */ + resultObj = Jim_NewDictObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { + Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetVariable(interp, argv[0], resultObj); + return JIM_OK; +} + +static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int len = 0; + + /* Not found means zero length */ + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + if (objPtr) { + len = Jim_DictSize(interp, objPtr); + if (len < 0) { + return JIM_ERR; + } + } + + Jim_SetResultInt(interp, len); + + return JIM_OK; +} + +static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + int rc = JIM_OK; + Jim_Obj *listObj = argv[1]; + + if (Jim_GetVariable(interp, argv[0], JIM_NONE) == NULL) { + /* Doesn't exist, so just set the list directly */ + return Jim_SetVariable(interp, argv[0], listObj); + } + + len = Jim_ListLength(interp, listObj); + if (len % 2) { + Jim_SetResultString(interp, "list must have an even number of elements", -1); + return JIM_ERR; + } + for (i = 0; i < len && rc == JIM_OK; i += 2) { + Jim_Obj *nameObj; + Jim_Obj *valueObj; + + Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE); + Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE); + + rc = Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj, JIM_ERRMSG); + } + + return rc; +} + +static const jim_subcmd_type array_command_table[] = { + { .cmd = "exists", + .args = "arrayName", + .function = array_cmd_exists, + .minargs = 1, + .maxargs = 1, + .description = "Does array exist?" + }, + { .cmd = "get", + .args = "arrayName ?pattern?", + .function = array_cmd_get, + .minargs = 1, + .maxargs = 2, + .description = "Array contents as name value list" + }, + { .cmd = "names", + .args = "arrayName ?pattern?", + .function = array_cmd_names, + .minargs = 1, + .maxargs = 2, + .description = "Array keys as a list" + }, + { .cmd = "set", + .args = "arrayName list", + .function = array_cmd_set, + .minargs = 2, + .maxargs = 2, + .description = "Set array from list" + }, + { .cmd = "size", + .args = "arrayName", + .function = array_cmd_size, + .minargs = 1, + .maxargs = 1, + .description = "Number of elements in array" + }, + { .cmd = "unset", + .args = "arrayName ?pattern?", + .function = array_cmd_unset, + .minargs = 1, + .maxargs = 2, + .description = "Unset elements of an array" + }, + { .cmd = 0, + } +}; + +int Jim_arrayInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-clock.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-clock.c new file mode 100755 index 0000000..51ffb51 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-clock.c @@ -0,0 +1,159 @@ + +/* + * tcl_clock.c + * + * Implements the clock command + */ + +/* For strptime() */ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <time.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* How big is big enough? */ + char buf[100]; + time_t t; + long seconds; + + const char *format = "%a %b %d %H:%M:%S %Z %Y"; + + if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { + return -1; + } + + if (argc == 3) { + format = Jim_String(argv[2]); + } + + if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { + return JIM_ERR; + } + t = seconds; + + strftime(buf, sizeof(buf), format, localtime(&t)); + + Jim_SetResultString(interp, buf, -1); + + return JIM_OK; +} + +#ifdef HAVE_STRPTIME +static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *pt; + struct tm tm; + time_t now = time(0); + + if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { + return -1; + } + + /* Initialise with the current date/time */ + localtime_r(&now, &tm); + + pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); + if (pt == 0 || *pt != 0) { + Jim_SetResultString(interp, "Failed to parse time according to format", -1); + return JIM_ERR; + } + + /* Now convert into a time_t */ + Jim_SetResultInt(interp, mktime(&tm)); + + return JIM_OK; +} +#endif + +static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResultInt(interp, time(NULL)); + + return JIM_OK; +} + +static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec); + + return JIM_OK; +} + +static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); + + return JIM_OK; +} + +static const jim_subcmd_type clock_command_table[] = { + { .cmd = "seconds", + .function = clock_cmd_seconds, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time as seconds since the epoch" + }, + { .cmd = "clicks", + .function = clock_cmd_micros, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in 'clicks'" + }, + { .cmd = "microseconds", + .function = clock_cmd_micros, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in microseconds" + }, + { .cmd = "milliseconds", + .function = clock_cmd_millis, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in milliseconds" + }, + { .cmd = "format", + .args = "seconds ?-format format?", + .function = clock_cmd_format, + .minargs = 1, + .maxargs = 3, + .description = "Format the given time" + }, +#ifdef HAVE_STRPTIME + { .cmd = "scan", + .args = "str -format format", + .function = clock_cmd_scan, + .minargs = 3, + .maxargs = 3, + .description = "Determine the time according to the given format" + }, +#endif + { 0 } +}; + +int Jim_clockInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in new file mode 100755 index 0000000..2394bc5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in @@ -0,0 +1,2 @@ +/* Public autoconf settings */ +@DEFINE_HAVE_LONG_LONG@ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c new file mode 100755 index 0000000..a7efdc2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c @@ -0,0 +1,760 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-eventloop.h" + +/* POSIX includes */ +#include <sys/time.h> +#include <sys/types.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#if defined(__MINGW32__) +#include <windows.h> +#include <winsock.h> +#define msleep Sleep +#ifndef HAVE_USLEEP +#define usleep(US) msleep((US) / 1000) +#endif +#else +#include <sys/select.h> + +#ifndef HAVE_USLEEP +/* XXX: Implement this in terms of select() or nanosleep() */ +#define usleep(US) +#endif +#define msleep(MS) sleep((MS) / 1000); usleep(((MS) % 1000) * 1000); +#endif + +/* --- */ + +/* File event structure */ +typedef struct Jim_FileEvent +{ + FILE *handle; + int mask; /* one of JIM_EVENT_(READABLE|WRITABLE|EXCEPTION) */ + Jim_FileProc *fileProc; + Jim_EventFinalizerProc *finalizerProc; + void *clientData; + struct Jim_FileEvent *next; +} Jim_FileEvent; + +/* Time event structure */ +typedef struct Jim_TimeEvent +{ + jim_wide id; /* time event identifier. */ + int mode; /* restart, repetitive .. UK */ + long initialms; /* initial relativ timer value UK */ + long when_sec; /* seconds */ + long when_ms; /* milliseconds */ + Jim_TimeProc *timeProc; + Jim_EventFinalizerProc *finalizerProc; + void *clientData; + struct Jim_TimeEvent *next; +} Jim_TimeEvent; + +/* Per-interp stucture containing the state of the event loop */ +typedef struct Jim_EventLoop +{ + jim_wide timeEventNextId; + Jim_FileEvent *fileEventHead; + Jim_TimeEvent *timeEventHead; + int suppress_bgerror; /* bgerror returned break, so don't call it again */ +} Jim_EventLoop; + +static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData); +static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData); + +int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr) +{ + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + Jim_CallFrame *savedFramePtr; + int retval; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + retval = Jim_EvalObj(interp, scriptObjPtr); + interp->framePtr = savedFramePtr; + /* Try to report the error (if any) via the bgerror proc */ + if (retval != JIM_OK && !eventLoop->suppress_bgerror) { + Jim_Obj *objv[2]; + int rc = JIM_ERR; + + objv[0] = Jim_NewStringObj(interp, "bgerror", -1); + objv[1] = Jim_GetResult(interp); + Jim_IncrRefCount(objv[0]); + Jim_IncrRefCount(objv[1]); + if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || (rc = Jim_EvalObjVector(interp, 2, objv)) != JIM_OK) { + if (rc == JIM_BREAK) { + /* No more bgerror calls */ + eventLoop->suppress_bgerror++; + } + else { + /* Report the error to stderr. */ + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + /* And reset the result */ + Jim_SetResultString(interp, "", -1); + } + } + Jim_DecrRefCount(interp, objv[0]); + Jim_DecrRefCount(interp, objv[1]); + } + return retval; +} + + +void Jim_CreateFileHandler(Jim_Interp *interp, FILE * handle, int mask, + Jim_FileProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc) +{ + Jim_FileEvent *fe; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + fe = Jim_Alloc(sizeof(*fe)); + fe->handle = handle; + fe->mask = mask; + fe->fileProc = proc; + fe->finalizerProc = finalizerProc; + fe->clientData = clientData; + fe->next = eventLoop->fileEventHead; + eventLoop->fileEventHead = fe; +} + +void Jim_DeleteFileHandler(Jim_Interp *interp, FILE * handle) +{ + Jim_FileEvent *fe, *prev = NULL; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + fe = eventLoop->fileEventHead; + while (fe) { + if (fe->handle == handle) { + if (prev == NULL) + eventLoop->fileEventHead = fe->next; + else + prev->next = fe->next; + if (fe->finalizerProc) + fe->finalizerProc(interp, fe->clientData); + Jim_Free(fe); + return; + } + prev = fe; + fe = fe->next; + } +} + +static void JimGetTime(long *seconds, long *milliseconds) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + *seconds = tv.tv_sec; + *milliseconds = tv.tv_usec / 1000; +} + +jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds, + Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc) +{ + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + jim_wide id = eventLoop->timeEventNextId++; + Jim_TimeEvent *te, *e, *prev; + long cur_sec, cur_ms; + + JimGetTime(&cur_sec, &cur_ms); + + te = Jim_Alloc(sizeof(*te)); + te->id = id; + te->mode = 0; + te->initialms = milliseconds; + te->when_sec = cur_sec + milliseconds / 1000; + te->when_ms = cur_ms + milliseconds % 1000; + if (te->when_ms >= 1000) { + te->when_sec++; + te->when_ms -= 1000; + } + te->timeProc = proc; + te->finalizerProc = finalizerProc; + te->clientData = clientData; + + /* Add to the appropriate place in the list */ + if (eventLoop->timeEventHead) { + prev = NULL; + for (e = eventLoop->timeEventHead; e; e = e->next) { + if (te->when_sec < e->when_sec || (te->when_sec == e->when_sec && te->when_ms < e->when_ms)) { + break; + } + prev = e; + } + if (prev) { + te->next = prev->next; + prev->next = te; + return id; + } + } + + te->next = eventLoop->timeEventHead; + eventLoop->timeEventHead = te; + + return id; +} + +static jim_wide JimParseAfterId(Jim_Obj *idObj) +{ + int len; + const char *tok = Jim_GetString(idObj, &len); + jim_wide id; + + if (strncmp(tok, "after#", 6) == 0 && Jim_StringToWide(tok + 6, &id, 10) == JIM_OK) { + /* Got an event by id */ + return id; + } + return -1; +} + +static jim_wide JimFindAfterByScript(Jim_EventLoop *eventLoop, Jim_Obj *scriptObj) +{ + Jim_TimeEvent *te; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + /* Is this an 'after' event? */ + if (te->timeProc == JimAfterTimeHandler) { + if (Jim_StringEqObj(scriptObj, te->clientData)) { + return te->id; + } + } + } + return -1; /* NO event with the specified ID found */ +} + +static Jim_TimeEvent *JimFindTimeHandlerById(Jim_EventLoop *eventLoop, jim_wide id) +{ + Jim_TimeEvent *te; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + if (te->id == id) { + return te; + } + } + return NULL; +} + +static Jim_TimeEvent *Jim_RemoveTimeHandler(Jim_EventLoop *eventLoop, jim_wide id) +{ + Jim_TimeEvent *te, *prev = NULL; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + if (te->id == id) { + if (prev == NULL) + eventLoop->timeEventHead = te->next; + else + prev->next = te->next; + return te; + } + prev = te; + } + return NULL; +} + +static void Jim_FreeTimeHandler(Jim_Interp *interp, Jim_TimeEvent *te) +{ + if (te->finalizerProc) + te->finalizerProc(interp, te->clientData); + Jim_Free(te); +} + +jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) +{ + Jim_TimeEvent *te; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + if (id >= eventLoop->timeEventNextId) { + return -2; /* wrong event ID */ + } + + te = Jim_RemoveTimeHandler(eventLoop, id); + if (te) { + jim_wide remain; + long cur_sec, cur_ms; + + JimGetTime(&cur_sec, &cur_ms); + + remain = (te->when_sec - cur_sec) * 1000; + remain += (te->when_ms - cur_ms); + remain = (remain < 0) ? 0 : remain; + + Jim_FreeTimeHandler(interp, te); + return remain; + } + return -1; /* NO event with the specified ID found */ +} + +/* --- POSIX version of Jim_ProcessEvents, for now the only available --- */ + +/* Process every pending time event, then every pending file event + * (that may be registered by time event callbacks just processed). + * Without special flags the function sleeps until some file event + * fires, or when the next time event occurrs (if any). + * + * If flags is 0, the function does nothing and returns. + * if flags has JIM_ALL_EVENTS set, all the kind of events are processed. + * if flags has JIM_FILE_EVENTS set, file events are processed. + * if flags has JIM_TIME_EVENTS set, time events are processed. + * if flags has JIM_DONT_WAIT set the function returns ASAP until all + * the events that's possible to process without to wait are processed. + * + * The function returns the number of events processed or -1 if + * there are no matching handlers, or -2 on error. + */ +int Jim_ProcessEvents(Jim_Interp *interp, int flags) +{ + jim_wide sleep_ms = -1; + int processed = 0; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + Jim_FileEvent *fe = eventLoop->fileEventHead; + Jim_TimeEvent *te; + jim_wide maxId; + + if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) { + /* No file events */ + if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) { + /* No time events */ + return -1; + } + } + + /* Note that we want call select() even if there are no + * file events to process as long as we want to process time + * events, in order to sleep until the next time event is ready + * to fire. */ + + if (flags & JIM_DONT_WAIT) { + /* Wait no time */ + sleep_ms = 0; + } + else if (flags & JIM_TIME_EVENTS) { + /* The nearest timer is always at the head of the list */ + if (eventLoop->timeEventHead) { + Jim_TimeEvent *shortest = eventLoop->timeEventHead; + long now_sec, now_ms; + + /* Calculate the time missing for the nearest + * timer to fire. */ + JimGetTime(&now_sec, &now_ms); + sleep_ms = 1000 * (shortest->when_sec - now_sec) + (shortest->when_ms - now_ms); + if (sleep_ms < 0) { + sleep_ms = 1; + } + } + else { + /* Wait forever */ + sleep_ms = -1; + } + } + +#ifdef HAVE_SELECT + if (flags & JIM_FILE_EVENTS) { + int retval; + struct timeval tv, *tvp = NULL; + fd_set rfds, wfds, efds; + int maxfd = -1; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + /* Check file events */ + while (fe != NULL) { + int fd = fileno(fe->handle); + + if (fe->mask & JIM_EVENT_READABLE) + FD_SET(fd, &rfds); + if (fe->mask & JIM_EVENT_WRITABLE) + FD_SET(fd, &wfds); + if (fe->mask & JIM_EVENT_EXCEPTION) + FD_SET(fd, &efds); + if (maxfd < fd) + maxfd = fd; + fe = fe->next; + } + + if (sleep_ms >= 0) { + tvp = &tv; + tvp->tv_sec = sleep_ms / 1000; + tvp->tv_usec = 1000 * (sleep_ms % 1000); + } + + retval = select(maxfd + 1, &rfds, &wfds, &efds, tvp); + + if (retval < 0) { + if (errno == EINVAL) { + /* This can happen on mingw32 if a non-socket filehandle is passed */ + Jim_SetResultString(interp, "non-waitable filehandle", -1); + return -2; + } + /* XXX: What about EINTR? */ + } + else if (retval > 0) { + fe = eventLoop->fileEventHead; + while (fe != NULL) { + int fd = fileno(fe->handle); + int mask = 0; + + if ((fe->mask & JIM_EVENT_READABLE) && FD_ISSET(fd, &rfds)) + mask |= JIM_EVENT_READABLE; + if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds)) + mask |= JIM_EVENT_WRITABLE; + if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds)) + mask |= JIM_EVENT_EXCEPTION; + + if (mask) { + if (fe->fileProc(interp, fe->clientData, mask) != JIM_OK) { + /* Remove the element on handler error */ + Jim_DeleteFileHandler(interp, fe->handle); + } + processed++; + /* After an event is processed our file event list + * may no longer be the same, so what we do + * is to clear the bit for this file descriptor and + * restart again from the head. */ + fe = eventLoop->fileEventHead; + FD_CLR(fd, &rfds); + FD_CLR(fd, &wfds); + FD_CLR(fd, &efds); + } + else { + fe = fe->next; + } + } + } + } +#else + if (sleep_ms > 0) { + msleep(sleep_ms); + } +#endif + + /* Check time events */ + te = eventLoop->timeEventHead; + maxId = eventLoop->timeEventNextId - 1; + while (te) { + long now_sec, now_ms; + jim_wide id; + + if (te->id > maxId) { + te = te->next; + continue; + } + JimGetTime(&now_sec, &now_ms); + if (now_sec > te->when_sec || (now_sec == te->when_sec && now_ms >= te->when_ms)) { + id = te->id; + /* Remove from the list before executing */ + Jim_RemoveTimeHandler(eventLoop, id); + te->timeProc(interp, te->clientData); + /* After an event is processed our time event list may + * no longer be the same, so we restart from head. + * Still we make sure to don't process events registered + * by event handlers itself in order to don't loop forever + * even in case an [after 0] that continuously register + * itself. To do so we saved the max ID we want to handle. */ + Jim_FreeTimeHandler(interp, te); + + te = eventLoop->timeEventHead; + processed++; + } + else { + te = te->next; + } + } + + return processed; +} + +/* ---------------------------------------------------------------------- */ + +static void JimELAssocDataDeleProc(Jim_Interp *interp, void *data) +{ + void *next; + Jim_FileEvent *fe; + Jim_TimeEvent *te; + Jim_EventLoop *eventLoop = data; + + fe = eventLoop->fileEventHead; + while (fe) { + next = fe->next; + if (fe->finalizerProc) + fe->finalizerProc(interp, fe->clientData); + Jim_Free(fe); + fe = next; + } + + te = eventLoop->timeEventHead; + while (te) { + next = te->next; + if (te->finalizerProc) + te->finalizerProc(interp, te->clientData); + Jim_Free(te); + te = next; + } + Jim_Free(data); +} + +static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + Jim_Obj *oldValue; + int rc; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "name"); + return JIM_ERR; + } + + oldValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE); + if (oldValue) { + Jim_IncrRefCount(oldValue); + } + else { + /* If a result was left, it is an error */ + int len; + Jim_GetString(interp->result, &len); + if (len) { + return JIM_ERR; + } + } + + eventLoop->suppress_bgerror = 0; + + while ((rc = Jim_ProcessEvents(interp, JIM_ALL_EVENTS)) >= 0) { + Jim_Obj *currValue; + currValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE); + /* Stop the loop if the vwait-ed variable changed value, + * or if was unset and now is set (or the contrary). */ + if ((oldValue && !currValue) || + (!oldValue && currValue) || + (oldValue && currValue && !Jim_StringEqObj(oldValue, currValue))) + break; + } + if (oldValue) + Jim_DecrRefCount(interp, oldValue); + + + if (rc == -2) { + return JIM_ERR; + } + + Jim_SetEmptyResult(interp); + return JIM_OK; +} + +static int JimELUpdateCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + static const char * const options[] = { + "idletasks", NULL + }; + enum { UPDATE_IDLE, UPDATE_NONE }; + int option = UPDATE_NONE; + int flags = JIM_TIME_EVENTS; + + if (argc == 1) { + flags = JIM_ALL_EVENTS; + } + else if (argc > 2 || Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + Jim_WrongNumArgs(interp, 1, argv, "?idletasks?"); + return JIM_ERR; + } + + eventLoop->suppress_bgerror = 0; + + while (Jim_ProcessEvents(interp, flags | JIM_DONT_WAIT) > 0) { + } + + return JIM_OK; +} + +static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_EvalObjBackground(interp, objPtr); +} + +static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_DecrRefCount(interp, objPtr); +} + +static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + jim_wide ms = 0, id; + Jim_Obj *objPtr, *idObjPtr; + static const char * const options[] = { + "cancel", "info", "idle", NULL + }; + enum + { AFTER_CANCEL, AFTER_INFO, AFTER_IDLE, AFTER_RESTART, AFTER_EXPIRE, AFTER_CREATE }; + int option = AFTER_CREATE; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arg ...?"); + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[1], &ms) != JIM_OK) { + if (Jim_GetEnum(interp, argv[1], options, &option, "argument", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_SetEmptyResult(interp); + } + else if (argc == 2) { + /* Simply a sleep */ + msleep(ms); + return JIM_OK; + } + + switch (option) { + case AFTER_IDLE: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "script ?script ...?"); + return JIM_ERR; + } + /* fall through */ + case AFTER_CREATE: { + Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2); + Jim_IncrRefCount(scriptObj); + id = Jim_CreateTimeHandler(interp, ms, JimAfterTimeHandler, scriptObj, + JimAfterTimeEventFinalizer); + objPtr = Jim_NewStringObj(interp, NULL, 0); + Jim_AppendString(interp, objPtr, "after#", -1); + idObjPtr = Jim_NewIntObj(interp, id); + Jim_IncrRefCount(idObjPtr); + Jim_AppendObj(interp, objPtr, idObjPtr); + Jim_DecrRefCount(interp, idObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + case AFTER_CANCEL: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "id|command"); + return JIM_ERR; + } + else { + jim_wide remain = 0; + + id = JimParseAfterId(argv[2]); + if (id < 0) { + /* Not an event id, so search by script */ + Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2); + id = JimFindAfterByScript(eventLoop, scriptObj); + Jim_FreeNewObj(interp, scriptObj); + if (id < 0) { + /* Not found */ + break; + } + } + remain = Jim_DeleteTimeHandler(interp, id); + if (remain >= 0) { + Jim_SetResultInt(interp, remain); + } + } + break; + + case AFTER_INFO: + if (argc == 2) { + Jim_TimeEvent *te = eventLoop->timeEventHead; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + char buf[30]; + const char *fmt = "after#%" JIM_WIDE_MODIFIER; + + while (te) { + snprintf(buf, sizeof(buf), fmt, te->id); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, buf, -1)); + te = te->next; + } + Jim_SetResult(interp, listObj); + } + else if (argc == 3) { + id = JimParseAfterId(argv[2]); + if (id >= 0) { + Jim_TimeEvent *e = JimFindTimeHandlerById(eventLoop, id); + if (e && e->timeProc == JimAfterTimeHandler) { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, e->clientData); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, e->initialms ? "timer" : "idle", -1)); + Jim_SetResult(interp, listObj); + return JIM_OK; + } + } + Jim_SetResultFormatted(interp, "event \"%#s\" doesn't exist", argv[2]); + return JIM_ERR; + } + else { + Jim_WrongNumArgs(interp, 2, argv, "?id?"); + return JIM_ERR; + } + break; + } + return JIM_OK; +} + +int Jim_eventloopInit(Jim_Interp *interp) +{ + Jim_EventLoop *eventLoop; + + if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + eventLoop = Jim_Alloc(sizeof(*eventLoop)); + eventLoop->fileEventHead = NULL; + eventLoop->timeEventHead = NULL; + eventLoop->timeEventNextId = 1; + eventLoop->suppress_bgerror = 0; + Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); + + Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL); + Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL); + Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h new file mode 100755 index 0000000..4da5408 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h @@ -0,0 +1,87 @@ +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ +/* ------ USAGE ------- + * + * In order to use this file from other extensions include it in every + * file where you need to call the eventloop API, also in the init + * function of your extension call Jim_ImportEventloopAPI(interp) + * after the Jim_InitExtension() call. + * + * See the UDP extension as example. + */ + + +#ifndef __JIM_EVENTLOOP_H__ +#define __JIM_EVENTLOOP_H__ + +#include <stdio.h> + +typedef int Jim_FileProc(Jim_Interp *interp, void *clientData, int mask); +typedef int Jim_SignalProc(Jim_Interp *interp, void *clientData, void *msg); +typedef void Jim_TimeProc(Jim_Interp *interp, void *clientData); +typedef void Jim_EventFinalizerProc(Jim_Interp *interp, void *clientData); + +/* File event structure */ +#define JIM_EVENT_READABLE 1 +#define JIM_EVENT_WRITABLE 2 +#define JIM_EVENT_EXCEPTION 4 + +JIM_EXPORT void Jim_CreateFileHandler (Jim_Interp *interp, + FILE *handle, int mask, + Jim_FileProc *proc, void *clientData, + Jim_EventFinalizerProc *finalizerProc); +JIM_EXPORT void Jim_DeleteFileHandler (Jim_Interp *interp, + FILE *handle); +JIM_EXPORT jim_wide Jim_CreateTimeHandler (Jim_Interp *interp, + jim_wide milliseconds, + Jim_TimeProc *proc, void *clientData, + Jim_EventFinalizerProc *finalizerProc); +JIM_EXPORT jim_wide Jim_DeleteTimeHandler (Jim_Interp *interp, jim_wide id); + +#define JIM_FILE_EVENTS 1 +#define JIM_TIME_EVENTS 2 +#define JIM_ALL_EVENTS (JIM_FILE_EVENTS|JIM_TIME_EVENTS) +#define JIM_DONT_WAIT 4 + +JIM_EXPORT int Jim_ProcessEvents (Jim_Interp *interp, int flags); +JIM_EXPORT int Jim_EvalObjBackground (Jim_Interp *interp, Jim_Obj *scriptObjPtr); + +int Jim_eventloopInit(Jim_Interp *interp); + +#endif /* __JIM_EVENTLOOP_H__ */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-exec.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-exec.c new file mode 100755 index 0000000..9088156 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-exec.c @@ -0,0 +1,1619 @@ +/* + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Implements the exec command for Jim + * + * Based on code originally from Tcl 6.7 by John Ousterhout. + * From that code: + * + * The Tcl_Fork and Tcl_WaitPids procedures are based on code + * contributed by Karl Lehenbauer, Mark Diekhans and Peter + * da Silva. + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <string.h> +#include <ctype.h> + +#include "jim.h" +#include "jimautoconf.h" + +#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) +/* Poor man's implementation of exec with system() + * The system() call *may* do command line redirection, etc. + * The standard output is not available. + * Can't redirect filehandles. + */ +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); + int i, j; + int rc; + + /* Create a quoted command line */ + for (i = 1; i < argc; i++) { + int len; + const char *arg = Jim_GetString(argv[i], &len); + + if (i > 1) { + Jim_AppendString(interp, cmdlineObj, " ", 1); + } + if (strpbrk(arg, "\\\" ") == NULL) { + /* No quoting required */ + Jim_AppendString(interp, cmdlineObj, arg, len); + continue; + } + + Jim_AppendString(interp, cmdlineObj, "\"", 1); + for (j = 0; j < len; j++) { + if (arg[j] == '\\' || arg[j] == '"') { + Jim_AppendString(interp, cmdlineObj, "\\", 1); + } + Jim_AppendString(interp, cmdlineObj, &arg[j], 1); + } + Jim_AppendString(interp, cmdlineObj, "\"", 1); + } + rc = system(Jim_String(cmdlineObj)); + + Jim_FreeNewObj(interp, cmdlineObj); + + if (rc) { + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc)); + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return JIM_ERR; + } + + return JIM_OK; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); + return JIM_OK; +} +#else +/* Full exec implementation for unix and mingw */ + +#include <errno.h> +#include <signal.h> + +#define XXX printf("@%s:%d\n", __FILE__, __LINE__); fflush(stdout); + +#if defined(__MINGW32__) + /* XXX: Should we use this implementation for cygwin too? */ + #include <fcntl.h> + + typedef HANDLE fdtype; + typedef HANDLE pidtype; + #define JIM_BAD_FD INVALID_HANDLE_VALUE + #define JIM_BAD_PID INVALID_HANDLE_VALUE + #define JimCloseFd CloseHandle + + #define WIFEXITED(STATUS) 1 + #define WEXITSTATUS(STATUS) (STATUS) + #define WIFSIGNALED(STATUS) 0 + #define WTERMSIG(STATUS) 0 + #define WNOHANG 1 + + static fdtype JimFileno(FILE *fh); + static pidtype JimWaitPid(pidtype pid, int *status, int nohang); + static fdtype JimDupFd(fdtype infd); + static fdtype JimOpenForRead(const char *filename); + static FILE *JimFdOpenForRead(fdtype fd); + static int JimPipe(fdtype pipefd[2]); + static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, + fdtype inputId, fdtype outputId, fdtype errorId); + static int JimErrno(void); +#else + #include "jim-signal.h" + #include <unistd.h> + #include <fcntl.h> + #include <sys/wait.h> + + typedef int fdtype; + typedef int pidtype; + #define JimPipe pipe + #define JimErrno() errno + #define JIM_BAD_FD -1 + #define JIM_BAD_PID -1 + #define JimFileno fileno + #define JimReadFd read + #define JimCloseFd close + #define JimWaitPid waitpid + #define JimDupFd dup + #define JimFdOpenForRead(FD) fdopen((FD), "r") + #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0) +#endif + +static const char *JimStrError(void); +static char **JimSaveEnv(char **env); +static void JimRestoreEnv(char **env); +static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, + pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId); +static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents); +static fdtype JimOpenForWrite(const char *filename, int append); +static int JimRewindFd(fdtype fd); + +static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) +{ + Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError()); +} + +static const char *JimStrError(void) +{ + return strerror(JimErrno()); +} + +static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) +{ + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } +} + +/** + * Read from 'fd', append the data to strObj and close 'fd'. + * Returns JIM_OK if OK, or JIM_ERR on error. + */ +static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj) +{ + char buf[256]; + FILE *fh = JimFdOpenForRead(fd); + if (fh == NULL) { + return JIM_ERR; + } + + while (1) { + int retval = fread(buf, 1, sizeof(buf), fh); + if (retval > 0) { + Jim_AppendString(interp, strObj, buf, retval); + } + if (retval != sizeof(buf)) { + break; + } + } + Jim_RemoveTrailingNewline(strObj); + fclose(fh); + return JIM_OK; +} + +/* + * If the last character of the result is a newline, then remove + * the newline character (the newline would just confuse things). + * + * Note: Ideally we could do this by just reducing the length of stringrep + * by 1, but there is no API for this :-( + */ +static void JimTrimTrailingNewline(Jim_Interp *interp) +{ + int len; + const char *p = Jim_GetString(Jim_GetResult(interp), &len); + + if (len > 0 && p[len - 1] == '\n') { + Jim_SetResultString(interp, p, len - 1); + } +} + +/** + * Builds the environment array from $::env + * + * If $::env is not set, simply returns environ. + * + * Otherwise allocates the environ array from the contents of $::env + * + * If the exec fails, memory can be freed via JimFreeEnv() + */ +static char **JimBuildEnv(Jim_Interp *interp) +{ +#if defined(jim_ext_tclcompat) + int i; + int size; + int num; + int n; + char **envptr; + char *envdata; + + Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); + + if (!objPtr) { + return Jim_GetEnviron(); + } + + /* We build the array as a single block consisting of the pointers followed by + * the strings. This has the advantage of being easy to allocate/free and being + * compatible with both unix and windows + */ + + /* Calculate the required size */ + num = Jim_ListLength(interp, objPtr); + if (num % 2) { + num--; + } + size = Jim_Length(objPtr); + /* We need one \0 and one equal sign for each element. + * A list has at least one space for each element except the first. + * We only need one extra char for the extra null terminator. + */ + size++; + + envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); + envdata = (char *)&envptr[num / 2 + 1]; + + n = 0; + for (i = 0; i < num; i += 2) { + const char *s1, *s2; + Jim_Obj *elemObj; + + Jim_ListIndex(interp, objPtr, i, &elemObj, JIM_NONE); + s1 = Jim_String(elemObj); + Jim_ListIndex(interp, objPtr, i + 1, &elemObj, JIM_NONE); + s2 = Jim_String(elemObj); + + envptr[n] = envdata; + envdata += sprintf(envdata, "%s=%s", s1, s2); + envdata++; + n++; + } + envptr[n] = NULL; + *envdata = 0; + + return envptr; +#else + return Jim_GetEnviron(); +#endif +} + +/** + * Frees the environment allocated by JimBuildEnv() + * + * Must pass original_environ. + */ +static void JimFreeEnv(char **env, char **original_environ) +{ +#ifdef jim_ext_tclcompat + if (env != original_environ) { + Jim_Free(env); + } +#endif +} + +/* + * Create error messages for unusual process exits. An + * extra newline gets appended to each error message, but + * it gets removed below (in the same fashion that an + * extra newline in the command's output is removed). + */ +static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) +{ + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + int rc = JIM_ERR; + + if (WIFEXITED(waitStatus)) { + if (WEXITSTATUS(waitStatus) == 0) { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); + rc = JIM_OK; + } + else { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); + } + } + else { + const char *type; + const char *action; + + if (WIFSIGNALED(waitStatus)) { + type = "CHILDKILLED"; + action = "killed"; + } + else { + type = "CHILDSUSP"; + action = "suspended"; + } + + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); + +#ifdef jim_ext_signal + Jim_SetResultFormatted(interp, "child %s by signal %s", action, Jim_SignalId(WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1)); +#else + Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); +#endif + } + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return rc; +} + +/* + * Data structures of the following type are used by JimFork and + * JimWaitPids to keep track of child processes. + */ + +struct WaitInfo +{ + pidtype pid; /* Process id of child. */ + int status; /* Status returned when child exited or suspended. */ + int flags; /* Various flag bits; see below for definitions. */ +}; + +struct WaitInfoTable { + struct WaitInfo *info; + int size; + int used; +}; + +/* + * Flag bits in WaitInfo structures: + * + * WI_DETACHED - Non-zero means no-one cares about the + * process anymore. Ignore it until it + * exits, then forget about it. + */ + +#define WI_DETACHED 2 + +#define WAIT_TABLE_GROW_BY 4 + +static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) +{ + struct WaitInfoTable *table = privData; + + Jim_Free(table->info); + Jim_Free(table); +} + +static struct WaitInfoTable *JimAllocWaitInfoTable(void) +{ + struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); + table->info = NULL; + table->size = table->used = 0; + + return table; +} + +/* + * The main [exec] command + */ +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + fdtype outputId; /* File id for output pipe. -1 + * means command overrode. */ + fdtype errorId; /* File id for temporary file + * containing error output. */ + pidtype *pidPtr; + int numPids, result; + + /* + * See if the command is to be run in background; if so, create + * the command, detach it, and return. + */ + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { + Jim_Obj *listObj; + int i; + + argc--; + numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); + if (numPids < 0) { + return JIM_ERR; + } + /* The return value is a list of the pids */ + listObj = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < numPids; i++) { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); + } + Jim_SetResult(interp, listObj); + JimDetachPids(interp, numPids, pidPtr); + Jim_Free(pidPtr); + return JIM_OK; + } + + /* + * Create the command's pipeline. + */ + numPids = + JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId); + + if (numPids < 0) { + return JIM_ERR; + } + + /* + * Read the child's output (if any) and put it into the result. + */ + Jim_SetResultString(interp, "", 0); + + result = JIM_OK; + if (outputId != JIM_BAD_FD) { + result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp)); + if (result < 0) { + Jim_SetResultErrno(interp, "error reading from output pipe"); + } + } + + if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) { + result = JIM_ERR; + } + return result; +} + +static void JimReapDetachedPids(struct WaitInfoTable *table) +{ + struct WaitInfo *waitPtr; + int count; + + if (!table) { + return; + } + + for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) { + if (waitPtr->flags & WI_DETACHED) { + int status; + pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); + if (pid != JIM_BAD_PID) { + if (waitPtr != &table->info[table->used - 1]) { + *waitPtr = table->info[table->used - 1]; + } + table->used--; + } + } + } +} + +/** + * Does waitpid() on the given pid, and then removes the + * entry from the wait table. + * + * Returns the pid if OK and updates *statusPtr with the status, + * or JIM_BAD_PID if the pid was not in the table. + */ +static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) +{ + int i; + + /* Find it in the table */ + for (i = 0; i < table->used; i++) { + if (pid == table->info[i].pid) { + /* wait for it */ + JimWaitPid(pid, statusPtr, 0); + + /* Remove it from the table */ + if (i != table->used - 1) { + table->info[i] = table->info[table->used - 1]; + } + table->used--; + return pid; + } + } + + /* Not found */ + return JIM_BAD_PID; +} + +/* + *---------------------------------------------------------------------- + * + * JimDetachPids -- + * + * This procedure is called to indicate that one or more child + * processes have been placed in background and are no longer + * cared about. These children can be cleaned up with JimReapDetachedPids(). + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) +{ + int j; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + for (j = 0; j < numPids; j++) { + /* Find it in the table */ + int i; + for (i = 0; i < table->used; i++) { + if (pidPtr[j] == table->info[i].pid) { + table->info[i].flags |= WI_DETACHED; + break; + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * JimCreatePipeline -- + * + * Given an argc/argv array, instantiate a pipeline of processes + * as described by the argv. + * + * Results: + * The return value is a count of the number of new processes + * created, or -1 if an error occurred while creating the pipeline. + * *pidArrayPtr is filled in with the address of a dynamically + * allocated array giving the ids of all of the processes. It + * is up to the caller to free this array when it isn't needed + * anymore. If inPipePtr is non-NULL, *inPipePtr is filled in + * with the file id for the input pipe for the pipeline (if any): + * the caller must eventually close this file. If outPipePtr + * isn't NULL, then *outPipePtr is filled in with the file id + * for the output pipe from the pipeline: the caller must close + * this file. If errFilePtr isn't NULL, then *errFilePtr is filled + * with a file id that may be used to read error output after the + * pipeline completes. + * + * Side effects: + * Processes and pipes are created. + * + *---------------------------------------------------------------------- + */ +static int +JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, + fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr) +{ + pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all + * the pids of child processes. */ + int numPids = 0; /* Actual number of processes that exist + * at *pidPtr right now. */ + int cmdCount; /* Count of number of distinct commands + * found in argc/argv. */ + const char *input = NULL; /* Describes input for pipeline, depending + * on "inputFile". NULL means take input + * from stdin/pipe. */ + +#define FILE_NAME 0 /* input/output: filename */ +#define FILE_APPEND 1 /* output only: filename, append */ +#define FILE_HANDLE 2 /* input/output: filehandle */ +#define FILE_TEXT 3 /* input only: input is actual text */ + + int inputFile = FILE_NAME; /* 1 means input is name of input file. + * 2 means input is filehandle name. + * 0 means input holds actual + * text to be input to command. */ + + int outputFile = FILE_NAME; /* 0 means output is the name of output file. + * 1 means output is the name of output file, and append. + * 2 means output is filehandle name. + * All this is ignored if output is NULL + */ + int errorFile = FILE_NAME; /* 0 means error is the name of error file. + * 1 means error is the name of error file, and append. + * 2 means error is filehandle name. + * All this is ignored if error is NULL + */ + const char *output = NULL; /* Holds name of output file to pipe to, + * or NULL if output goes to stdout/pipe. */ + const char *error = NULL; /* Holds name of stderr file to pipe to, + * or NULL if stderr goes to stderr/pipe. */ + fdtype inputId = JIM_BAD_FD; + /* Readable file id input to current command in + * pipeline (could be file or pipe). JIM_BAD_FD + * means use stdin. */ + fdtype outputId = JIM_BAD_FD; + /* Writable file id for output from current + * command in pipeline (could be file or pipe). + * JIM_BAD_FD means use stdout. */ + fdtype errorId = JIM_BAD_FD; + /* Writable file id for all standard error + * output from all commands in pipeline. JIM_BAD_FD + * means use stderr. */ + fdtype lastOutputId = JIM_BAD_FD; + /* Write file id for output from last command + * in pipeline (could be file or pipe). + * -1 means use stdout. */ + fdtype pipeIds[2]; /* File ids for pipe that's being created. */ + int firstArg, lastArg; /* Indexes of first and last arguments in + * current command. */ + int lastBar; + int i; + pidtype pid; + char **save_environ; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + /* Holds the args which will be used to exec */ + char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); + int arg_count = 0; + + JimReapDetachedPids(table); + + if (inPipePtr != NULL) { + *inPipePtr = JIM_BAD_FD; + } + if (outPipePtr != NULL) { + *outPipePtr = JIM_BAD_FD; + } + if (errFilePtr != NULL) { + *errFilePtr = JIM_BAD_FD; + } + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + + /* + * First, scan through all the arguments to figure out the structure + * of the pipeline. Count the number of distinct processes (it's the + * number of "|" arguments). If there are "<", "<<", or ">" arguments + * then make note of input and output redirection and remove these + * arguments and the arguments that follow them. + */ + cmdCount = 1; + lastBar = -1; + for (i = 0; i < argc; i++) { + const char *arg = Jim_String(argv[i]); + + if (arg[0] == '<') { + inputFile = FILE_NAME; + input = arg + 1; + if (*input == '<') { + inputFile = FILE_TEXT; + input++; + } + else if (*input == '@') { + inputFile = FILE_HANDLE; + input++; + } + + if (!*input && ++i < argc) { + input = Jim_String(argv[i]); + } + } + else if (arg[0] == '>') { + int dup_error = 0; + + outputFile = FILE_NAME; + + output = arg + 1; + if (*output == '>') { + outputFile = FILE_APPEND; + output++; + } + if (*output == '&') { + /* Redirect stderr too */ + output++; + dup_error = 1; + } + if (*output == '@') { + outputFile = FILE_HANDLE; + output++; + } + if (!*output && ++i < argc) { + output = Jim_String(argv[i]); + } + if (dup_error) { + errorFile = outputFile; + error = output; + } + } + else if (arg[0] == '2' && arg[1] == '>') { + error = arg + 2; + errorFile = FILE_NAME; + + if (*error == '@') { + errorFile = FILE_HANDLE; + error++; + } + else if (*error == '>') { + errorFile = FILE_APPEND; + error++; + } + if (!*error && ++i < argc) { + error = Jim_String(argv[i]); + } + } + else { + if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) { + if (i == lastBar + 1 || i == argc - 1) { + Jim_SetResultString(interp, "illegal use of | or |& in command", -1); + goto badargs; + } + lastBar = i; + cmdCount++; + } + /* Either |, |& or a "normal" arg, so store it in the arg array */ + arg_array[arg_count++] = (char *)arg; + continue; + } + + if (i >= argc) { + Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg); + goto badargs; + } + } + + if (arg_count == 0) { + Jim_SetResultString(interp, "didn't specify command to execute", -1); +badargs: + Jim_Free(arg_array); + return -1; + } + + /* Must do this before vfork(), so do it now */ + save_environ = JimSaveEnv(JimBuildEnv(interp)); + + /* + * Set up the redirected input source for the pipeline, if + * so requested. + */ + if (input != NULL) { + if (inputFile == FILE_TEXT) { + /* + * Immediate data in command. Create temporary file and + * put data into file. + */ + inputId = JimCreateTemp(interp, input); + if (inputId == JIM_BAD_FD) { + goto error; + } + } + else if (inputFile == FILE_HANDLE) { + /* Should be a file descriptor */ + Jim_Obj *fhObj = Jim_NewStringObj(interp, input, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + inputId = JimDupFd(JimFileno(fh)); + } + else { + /* + * File redirection. Just open the file. + */ + inputId = JimOpenForRead(input); + if (inputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError()); + goto error; + } + } + } + else if (inPipePtr != NULL) { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create input pipe for command"); + goto error; + } + inputId = pipeIds[0]; + *inPipePtr = pipeIds[1]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + + /* + * Set up the redirected output sink for the pipeline from one + * of two places, if requested. + */ + if (output != NULL) { + if (outputFile == FILE_HANDLE) { + Jim_Obj *fhObj = Jim_NewStringObj(interp, output, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + fflush(fh); + lastOutputId = JimDupFd(JimFileno(fh)); + } + else { + /* + * Output is to go to a file. + */ + lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND); + if (lastOutputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError()); + goto error; + } + } + } + else if (outPipePtr != NULL) { + /* + * Output is to go to a pipe. + */ + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create output pipe"); + goto error; + } + lastOutputId = pipeIds[1]; + *outPipePtr = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + /* If we are redirecting stderr with 2>filename or 2>@fileId, then we ignore errFilePtr */ + if (error != NULL) { + if (errorFile == FILE_HANDLE) { + if (strcmp(error, "1") == 0) { + /* Special 2>@1 */ + if (lastOutputId != JIM_BAD_FD) { + errorId = JimDupFd(lastOutputId); + } + else { + /* No redirection of stdout, so just use 2>@stdout */ + error = "stdout"; + } + } + if (errorId == JIM_BAD_FD) { + Jim_Obj *fhObj = Jim_NewStringObj(interp, error, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + fflush(fh); + errorId = JimDupFd(JimFileno(fh)); + } + } + else { + /* + * Output is to go to a file. + */ + errorId = JimOpenForWrite(error, errorFile == FILE_APPEND); + if (errorId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError()); + goto error; + } + } + } + else if (errFilePtr != NULL) { + /* + * Set up the standard error output sink for the pipeline, if + * requested. Use a temporary file which is opened, then deleted. + * Could potentially just use pipe, but if it filled up it could + * cause the pipeline to deadlock: we'd be waiting for processes + * to complete before reading stderr, and processes couldn't complete + * because stderr was backed up. + */ + errorId = JimCreateTemp(interp, NULL); + if (errorId == JIM_BAD_FD) { + goto error; + } + *errFilePtr = JimDupFd(errorId); + } + + /* + * Scan through the argc array, forking off a process for each + * group of arguments between "|" arguments. + */ + + pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); + for (i = 0; i < numPids; i++) { + pidPtr[i] = JIM_BAD_PID; + } + for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { + int pipe_dup_err = 0; + fdtype origErrorId = errorId; + + for (lastArg = firstArg; lastArg < arg_count; lastArg++) { + if (arg_array[lastArg][0] == '|') { + if (arg_array[lastArg][1] == '&') { + pipe_dup_err = 1; + } + break; + } + } + /* Replace | with NULL for execv() */ + arg_array[lastArg] = NULL; + if (lastArg == arg_count) { + outputId = lastOutputId; + } + else { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create pipe"); + goto error; + } + outputId = pipeIds[1]; + } + + /* Now fork the child */ + +#ifdef __MINGW32__ + pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); + if (pid == JIM_BAD_PID) { + Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); + goto error; + } +#else + /* + * Disable SIGPIPE signals: if they were allowed, this process + * might go away unexpectedly if children misbehave. This code + * can potentially interfere with other application code that + * expects to handle SIGPIPEs; what's really needed is an + * arbiter for signals to allow them to be "shared". + */ + if (table->info == NULL) { + (void)signal(SIGPIPE, SIG_IGN); + } + + /* Need to do this befor vfork() */ + if (pipe_dup_err) { + errorId = outputId; + } + + /* + * Make a new process and enter it into the table if the fork + * is successful. + */ + pid = vfork(); + if (pid < 0) { + Jim_SetResultErrno(interp, "couldn't fork child process"); + goto error; + } + if (pid == 0) { + /* Child */ + + if (inputId != -1) dup2(inputId, 0); + if (outputId != -1) dup2(outputId, 1); + if (errorId != -1) dup2(errorId, 2); + + for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { + close(i); + } + + execvp(arg_array[firstArg], &arg_array[firstArg]); + + /* Need to prep an error message before vfork(), just in case */ + fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]); + _exit(127); + } +#endif + + /* parent */ + + /* + * Enlarge the wait table if there isn't enough space for a new + * entry. + */ + if (table->used == table->size) { + table->size += WAIT_TABLE_GROW_BY; + table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); + } + + table->info[table->used].pid = pid; + table->info[table->used].flags = 0; + table->used++; + + pidPtr[numPids] = pid; + + /* Restore in case of pipe_dup_err */ + errorId = origErrorId; + + /* + * Close off our copies of file descriptors that were set up for + * this child, then set up the input for the next child. + */ + + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (outputId != JIM_BAD_FD) { + JimCloseFd(outputId); + } + inputId = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + *pidArrayPtr = pidPtr; + + /* + * All done. Cleanup open files lying around and then return. + */ + + cleanup: + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (lastOutputId != JIM_BAD_FD) { + JimCloseFd(lastOutputId); + } + if (errorId != JIM_BAD_FD) { + JimCloseFd(errorId); + } + Jim_Free(arg_array); + + JimRestoreEnv(save_environ); + + return numPids; + + /* + * An error occurred. There could have been extra files open, such + * as pipes between children. Clean them all up. Detach any child + * processes that have been created. + */ + + error: + if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) { + JimCloseFd(*inPipePtr); + *inPipePtr = JIM_BAD_FD; + } + if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) { + JimCloseFd(*outPipePtr); + *outPipePtr = JIM_BAD_FD; + } + if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) { + JimCloseFd(*errFilePtr); + *errFilePtr = JIM_BAD_FD; + } + if (pipeIds[0] != JIM_BAD_FD) { + JimCloseFd(pipeIds[0]); + } + if (pipeIds[1] != JIM_BAD_FD) { + JimCloseFd(pipeIds[1]); + } + if (pidPtr != NULL) { + for (i = 0; i < numPids; i++) { + if (pidPtr[i] != JIM_BAD_PID) { + JimDetachPids(interp, 1, &pidPtr[i]); + } + } + Jim_Free(pidPtr); + } + numPids = -1; + goto cleanup; +} + +/* + *---------------------------------------------------------------------- + * + * JimCleanupChildren -- + * + * This is a utility procedure used to wait for child processes + * to exit, record information about abnormal exits, and then + * collect any stderr output generated by them. + * + * Results: + * The return value is a standard Tcl result. If anything at + * weird happened with the child processes, JIM_ERROR is returned + * and a message is left in interp->result. + * + * Side effects: + * If the last character of interp->result is a newline, then it + * is removed. File errorId gets closed, and pidPtr is freed + * back to the storage allocator. + * + *---------------------------------------------------------------------- + */ + +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId) +{ + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + int result = JIM_OK; + int i; + + for (i = 0; i < numPids; i++) { + int waitStatus = 0; + if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { + if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) { + result = JIM_ERR; + } + } + } + Jim_Free(pidPtr); + + /* + * Read the standard error file. If there's anything there, + * then add the file's contents to the result + * string. + */ + if (errorId != JIM_BAD_FD) { + JimRewindFd(errorId); + if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { + result = JIM_ERR; + } + } + + JimTrimTrailingNewline(interp); + + return result; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); + return JIM_OK; +} + +#if defined(__MINGW32__) +/* Windows-specific (mingw) implementation */ + +static SECURITY_ATTRIBUTES *JimStdSecAttrs(void) +{ + static SECURITY_ATTRIBUTES secAtts; + + secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); + secAtts.lpSecurityDescriptor = NULL; + secAtts.bInheritHandle = TRUE; + return &secAtts; +} + +static int JimErrno(void) +{ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: return ENOENT; + case ERROR_PATH_NOT_FOUND: return ENOENT; + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; + case ERROR_ACCESS_DENIED: return EACCES; + case ERROR_INVALID_HANDLE: return EBADF; + case ERROR_BAD_ENVIRONMENT: return E2BIG; + case ERROR_BAD_FORMAT: return ENOEXEC; + case ERROR_INVALID_ACCESS: return EACCES; + case ERROR_INVALID_DRIVE: return ENOENT; + case ERROR_CURRENT_DIRECTORY: return EACCES; + case ERROR_NOT_SAME_DEVICE: return EXDEV; + case ERROR_NO_MORE_FILES: return ENOENT; + case ERROR_WRITE_PROTECT: return EROFS; + case ERROR_BAD_UNIT: return ENXIO; + case ERROR_NOT_READY: return EBUSY; + case ERROR_BAD_COMMAND: return EIO; + case ERROR_CRC: return EIO; + case ERROR_BAD_LENGTH: return EIO; + case ERROR_SEEK: return EIO; + case ERROR_WRITE_FAULT: return EIO; + case ERROR_READ_FAULT: return EIO; + case ERROR_GEN_FAILURE: return EIO; + case ERROR_SHARING_VIOLATION: return EACCES; + case ERROR_LOCK_VIOLATION: return EACCES; + case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; + case ERROR_HANDLE_DISK_FULL: return ENOSPC; + case ERROR_NOT_SUPPORTED: return ENODEV; + case ERROR_REM_NOT_LIST: return EBUSY; + case ERROR_DUP_NAME: return EEXIST; + case ERROR_BAD_NETPATH: return ENOENT; + case ERROR_NETWORK_BUSY: return EBUSY; + case ERROR_DEV_NOT_EXIST: return ENODEV; + case ERROR_TOO_MANY_CMDS: return EAGAIN; + case ERROR_ADAP_HDW_ERR: return EIO; + case ERROR_BAD_NET_RESP: return EIO; + case ERROR_UNEXP_NET_ERR: return EIO; + case ERROR_NETNAME_DELETED: return ENOENT; + case ERROR_NETWORK_ACCESS_DENIED: return EACCES; + case ERROR_BAD_DEV_TYPE: return ENODEV; + case ERROR_BAD_NET_NAME: return ENOENT; + case ERROR_TOO_MANY_NAMES: return ENFILE; + case ERROR_TOO_MANY_SESS: return EIO; + case ERROR_SHARING_PAUSED: return EAGAIN; + case ERROR_REDIR_PAUSED: return EAGAIN; + case ERROR_FILE_EXISTS: return EEXIST; + case ERROR_CANNOT_MAKE: return ENOSPC; + case ERROR_OUT_OF_STRUCTURES: return ENFILE; + case ERROR_ALREADY_ASSIGNED: return EEXIST; + case ERROR_INVALID_PASSWORD: return EPERM; + case ERROR_NET_WRITE_FAULT: return EIO; + case ERROR_NO_PROC_SLOTS: return EAGAIN; + case ERROR_DISK_CHANGE: return EXDEV; + case ERROR_BROKEN_PIPE: return EPIPE; + case ERROR_OPEN_FAILED: return ENOENT; + case ERROR_DISK_FULL: return ENOSPC; + case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; + case ERROR_INVALID_TARGET_HANDLE: return EBADF; + case ERROR_INVALID_NAME: return ENOENT; + case ERROR_PROC_NOT_FOUND: return ESRCH; + case ERROR_WAIT_NO_CHILDREN: return ECHILD; + case ERROR_CHILD_NOT_COMPLETE: return ECHILD; + case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; + case ERROR_SEEK_ON_DEVICE: return ESPIPE; + case ERROR_BUSY_DRIVE: return EAGAIN; + case ERROR_DIR_NOT_EMPTY: return EEXIST; + case ERROR_NOT_LOCKED: return EACCES; + case ERROR_BAD_PATHNAME: return ENOENT; + case ERROR_LOCK_FAILED: return EACCES; + case ERROR_ALREADY_EXISTS: return EEXIST; + case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; + case ERROR_BAD_PIPE: return EPIPE; + case ERROR_PIPE_BUSY: return EAGAIN; + case ERROR_PIPE_NOT_CONNECTED: return EPIPE; + case ERROR_DIRECTORY: return ENOTDIR; + } + return EINVAL; +} + +static int JimPipe(fdtype pipefd[2]) +{ + if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) { + return 0; + } + return -1; +} + +static fdtype JimDupFd(fdtype infd) +{ + fdtype dupfd; + pidtype pid = GetCurrentProcess(); + + if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + return dupfd; + } + return JIM_BAD_FD; +} + +static int JimRewindFd(fdtype fd) +{ + return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0; +} + +#if 0 +static int JimReadFd(fdtype fd, char *buffer, size_t len) +{ + DWORD num; + + if (ReadFile(fd, buffer, len, &num, NULL)) { + return num; + } + if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) { + return 0; + } + return -1; +} +#endif + +static FILE *JimFdOpenForRead(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r"); +} + +static fdtype JimFileno(FILE *fh) +{ + return (fdtype)_get_osfhandle(_fileno(fh)); +} + +static fdtype JimOpenForRead(const char *filename) +{ + return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), OPEN_EXISTING, 0, NULL); +} + +static fdtype JimOpenForWrite(const char *filename, int append) +{ + return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL); +} + +static FILE *JimFdOpenForWrite(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w"); +} + +static pidtype JimWaitPid(pidtype pid, int *status, int nohang) +{ + DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { + /* WAIT_TIMEOUT can only happend with WNOHANG */ + return JIM_BAD_PID; + } + GetExitCodeProcess(pid, &ret); + *status = ret; + CloseHandle(pid); + return pid; +} + +static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents) +{ + char name[MAX_PATH]; + HANDLE handle; + + if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { + return JIM_BAD_FD; + } + + handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(), + CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (handle == INVALID_HANDLE_VALUE) { + goto error; + } + + if (contents != NULL) { + /* Use fdopen() to get automatic text-mode translation */ + FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); + if (fh == NULL) { + goto error; + } + + if (fwrite(contents, strlen(contents), 1, fh) != 1) { + fclose(fh); + goto error; + } + fseek(fh, 0, SEEK_SET); + fclose(fh); + } + return handle; + + error: + Jim_SetResultErrno(interp, "failed to create temp file"); + CloseHandle(handle); + DeleteFile(name); + return JIM_BAD_FD; +} + +static int +JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) +{ + int i; + static char extensions[][5] = {".exe", "", ".bat"}; + + for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { + lstrcpyn(fullPath, originalName, MAX_PATH - 5); + lstrcat(fullPath, extensions[i]); + + if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) { + continue; + } + if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) { + continue; + } + return 0; + } + + return -1; +} + +static char **JimSaveEnv(char **env) +{ + return env; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(env, NULL); +} + +static Jim_Obj * +JimWinBuildCommandLine(Jim_Interp *interp, char **argv) +{ + char *start, *special; + int quote, i; + + Jim_Obj *strObj = Jim_NewStringObj(interp, "", 0); + + for (i = 0; argv[i]; i++) { + if (i > 0) { + Jim_AppendString(interp, strObj, " ", 1); + } + + if (argv[i][0] == '\0') { + quote = 1; + } + else { + quote = 0; + for (start = argv[i]; *start != '\0'; start++) { + if (isspace(UCHAR(*start))) { + quote = 1; + break; + } + } + } + if (quote) { + Jim_AppendString(interp, strObj, "\"" , 1); + } + + start = argv[i]; + for (special = argv[i]; ; ) { + if ((*special == '\\') && (special[1] == '\\' || + special[1] == '"' || (quote && special[1] == '\0'))) { + Jim_AppendString(interp, strObj, start, special - start); + start = special; + while (1) { + special++; + if (*special == '"' || (quote && *special == '\0')) { + /* + * N backslashes followed a quote -> insert + * N * 2 + 1 backslashes then a quote. + */ + + Jim_AppendString(interp, strObj, start, special - start); + break; + } + if (*special != '\\') { + break; + } + } + Jim_AppendString(interp, strObj, start, special - start); + start = special; + } + if (*special == '"') { + if (special == start) { + Jim_AppendString(interp, strObj, "\"", 1); + } + else { + Jim_AppendString(interp, strObj, start, special - start); + } + Jim_AppendString(interp, strObj, "\\\"", 2); + start = special + 1; + } + if (*special == '\0') { + break; + } + special++; + } + Jim_AppendString(interp, strObj, start, special - start); + if (quote) { + Jim_AppendString(interp, strObj, "\"", 1); + } + } + return strObj; +} + +static pidtype +JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId) +{ + STARTUPINFO startInfo; + PROCESS_INFORMATION procInfo; + HANDLE hProcess, h; + char execPath[MAX_PATH]; + char *originalName; + pidtype pid = JIM_BAD_PID; + Jim_Obj *cmdLineObj; + + if (JimWinFindExecutable(argv[0], execPath) < 0) { + return JIM_BAD_PID; + } + originalName = argv[0]; + argv[0] = execPath; + + hProcess = GetCurrentProcess(); + cmdLineObj = JimWinBuildCommandLine(interp, argv); + + /* + * STARTF_USESTDHANDLES must be used to pass handles to child process. + * Using SetStdHandle() and/or dup2() only works when a console mode + * parent process is spawning an attached console mode child process. + */ + + ZeroMemory(&startInfo, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); + startInfo.dwFlags = STARTF_USESTDHANDLES; + startInfo.hStdInput = INVALID_HANDLE_VALUE; + startInfo.hStdOutput= INVALID_HANDLE_VALUE; + startInfo.hStdError = INVALID_HANDLE_VALUE; + + /* + * Duplicate all the handles which will be passed off as stdin, stdout + * and stderr of the child process. The duplicate handles are set to + * be inheritable, so the child process can use them. + */ + if (inputId == JIM_BAD_FD) { + if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { + CloseHandle(h); + } + } else { + DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdInput == JIM_BAD_FD) { + goto end; + } + + if (outputId == JIM_BAD_FD) { + startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdOutput == JIM_BAD_FD) { + goto end; + } + + if (errorId == JIM_BAD_FD) { + /* + * If handle was not set, errors should be sent to an infinitely + * deep sink. + */ + + startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdError == JIM_BAD_FD) { + goto end; + } + + if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, + 0, env, NULL, &startInfo, &procInfo)) { + goto end; + } + + /* + * "When an application spawns a process repeatedly, a new thread + * instance will be created for each process but the previous + * instances may not be cleaned up. This results in a significant + * virtual memory loss each time the process is spawned. If there + * is a WaitForInputIdle() call between CreateProcess() and + * CloseHandle(), the problem does not occur." PSS ID Number: Q124121 + */ + + WaitForInputIdle(procInfo.hProcess, 5000); + CloseHandle(procInfo.hThread); + + pid = procInfo.hProcess; + + end: + Jim_FreeNewObj(interp, cmdLineObj); + if (startInfo.hStdInput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdInput); + } + if (startInfo.hStdOutput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdOutput); + } + if (startInfo.hStdError != JIM_BAD_FD) { + CloseHandle(startInfo.hStdError); + } + return pid; +} +#else +/* Unix-specific implementation */ +static int JimOpenForWrite(const char *filename, int append) +{ + return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); +} + +static int JimRewindFd(int fd) +{ + return lseek(fd, 0L, SEEK_SET); +} + +static int JimCreateTemp(Jim_Interp *interp, const char *contents) +{ + char inName[] = "/tmp/tcl.tmp.XXXXXX"; + + int fd = mkstemp(inName); + if (fd == JIM_BAD_FD) { + Jim_SetResultErrno(interp, "couldn't create temp file"); + return -1; + } + unlink(inName); + if (contents) { + int length = strlen(contents); + if (write(fd, contents, length) != length) { + Jim_SetResultErrno(interp, "couldn't write temp file"); + close(fd); + return -1; + } + lseek(fd, 0L, SEEK_SET); + } + return fd; +} + +static char **JimSaveEnv(char **env) +{ + char **saveenv = Jim_GetEnviron(); + Jim_SetEnviron(env); + return saveenv; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(Jim_GetEnviron(), env); + Jim_SetEnviron(env); +} +#endif +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-file.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-file.c new file mode 100755 index 0000000..7b48368 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-file.c @@ -0,0 +1,929 @@ +/* + * Implements the file command for jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +# ifndef MAXPATHLEN +# define MAXPATHLEN JIM_PATH_LEN +# endif + +/* + *---------------------------------------------------------------------- + * + * JimGetFileType -- + * + * Given a mode word, returns a string identifying the type of a + * file. + * + * Results: + * A static text string giving the file type from mode. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static const char *JimGetFileType(int mode) +{ + if (S_ISREG(mode)) { + return "file"; + } + else if (S_ISDIR(mode)) { + return "directory"; + } + else if (S_ISCHR(mode)) { + return "characterSpecial"; + } + else if (S_ISBLK(mode)) { + return "blockSpecial"; + } + else if (S_ISFIFO(mode)) { + return "fifo"; +#ifdef S_ISLNK + } + else if (S_ISLNK(mode)) { + return "link"; +#endif +#ifdef S_ISSOCK + } + else if (S_ISSOCK(mode)) { + return "socket"; +#endif + } + return "unknown"; +} + +/* + *---------------------------------------------------------------------- + * + * StoreStatData -- + * + * This is a utility procedure that breaks out the fields of a + * "stat" structure and stores them in textual form into the + * elements of an associative array. + * + * Results: + * Returns a standard Tcl return value. If an error occurs then + * a message is left in interp->result. + * + * Side effects: + * Elements of the associative array given by "varName" are modified. + * + *---------------------------------------------------------------------- + */ + +static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, + jim_wide value) +{ + Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); + Jim_Obj *valobj = Jim_NewWideObj(interp, value); + + if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { + Jim_FreeObj(interp, nameobj); + Jim_FreeObj(interp, valobj); + return JIM_ERR; + } + return JIM_OK; +} + +static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, + const char *value) +{ + Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); + Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); + + if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { + Jim_FreeObj(interp, nameobj); + Jim_FreeObj(interp, valobj); + return JIM_ERR; + } + return JIM_OK; +} + +static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) +{ + if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { + Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variables isn't array", varName); + return JIM_ERR; + } + set_array_int_value(interp, varName, "ino", sb->st_ino); + set_array_int_value(interp, varName, "mode", sb->st_mode); + set_array_int_value(interp, varName, "nlink", sb->st_nlink); + set_array_int_value(interp, varName, "uid", sb->st_uid); + set_array_int_value(interp, varName, "gid", sb->st_gid); + set_array_int_value(interp, varName, "size", sb->st_size); + set_array_int_value(interp, varName, "atime", sb->st_atime); + set_array_int_value(interp, varName, "mtime", sb->st_mtime); + set_array_int_value(interp, varName, "ctime", sb->st_ctime); + set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); + + /* And also return the value */ + Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); + + return JIM_OK; +} + +static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *p = strrchr(path, '/'); + + if (!p) { + Jim_SetResultString(interp, ".", -1); + } + else if (p == path) { + Jim_SetResultString(interp, "/", -1); + } +#if defined(__MINGW32__) + else if (p[-1] == ':') { + /* z:/dir => z:/ */ + Jim_SetResultString(interp, path, p - path + 1); + } +#endif + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash > p)) { + Jim_SetResult(interp, argv[0]); + } + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash >= p)) { + p = ""; + } + Jim_SetResultString(interp, p, -1); + return JIM_OK; +} + +static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + + if (lastSlash) { + Jim_SetResultString(interp, lastSlash + 1, -1); + } + else { + Jim_SetResult(interp, argv[0]); + } + return JIM_OK; +} + +static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_REALPATH + const char *path = Jim_String(argv[0]); + char *newname = Jim_Alloc(MAXPATHLEN + 1); + + if (realpath(path, newname)) { + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1)); + } + else { + Jim_Free(newname); + Jim_SetResult(interp, argv[0]); + } + return JIM_OK; +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif +} + +static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + char *newname = Jim_Alloc(MAXPATHLEN + 1); + char *last = newname; + + *newname = 0; + + /* Simple implementation for now */ + for (i = 0; i < argc; i++) { + int len; + const char *part = Jim_GetString(argv[i], &len); + + if (*part == '/') { + /* Absolute component, so go back to the start */ + last = newname; + } +#if defined(__MINGW32__) + else if (strchr(part, ':')) { + /* Absolute compontent on mingw, so go back to the start */ + last = newname; + } +#endif + else if (part[0] == '.') { + if (part[1] == '/') { + part += 2; + len -= 2; + } + else if (part[1] == 0 && last != newname) { + /* Adding '.' to an existing path does nothing */ + continue; + } + } + + /* Add a slash if needed */ + if (last != newname && last[-1] != '/') { + *last++ = '/'; + } + + if (len) { + if (last + len - newname >= MAXPATHLEN) { + Jim_Free(newname); + Jim_SetResultString(interp, "Path too long", -1); + return JIM_ERR; + } + memcpy(last, part, len); + last += len; + } + + /* Remove a slash if needed */ + if (last > newname + 1 && last[-1] == '/') { + *--last = 0; + } + } + + *last = 0; + + /* Probably need to handle some special cases ... */ + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); + + return JIM_OK; +} + +static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) +{ + const char *path = Jim_String(filename); + int rc = access(path, mode); + + Jim_SetResultBool(interp, rc != -1); + + return JIM_OK; +} + +static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], R_OK); +} + +static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], W_OK); +} + +static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], X_OK); +} + +static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], F_OK); +} + +static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int force = Jim_CompareStringImmediate(interp, argv[0], "-force"); + + if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) { + argc++; + argv--; + } + + while (argc--) { + const char *path = Jim_String(argv[0]); + + if (unlink(path) == -1 && errno != ENOENT) { + if (rmdir(path) == -1) { + /* Maybe try using the script helper */ + if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { + Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + } + } + argv++; + } + return JIM_OK; +} + +#ifdef HAVE_MKDIR_ONE_ARG +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME) +#else +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755) +#endif + +/** + * Create directory, creating all intermediate paths if necessary. + * + * Returns 0 if OK or -1 on failure (and sets errno) + * + * Note: The path may be modified. + */ +static int mkdir_all(char *path) +{ + int ok = 1; + + /* First time just try to make the dir */ + goto first; + + while (ok--) { + /* Must have failed the first time, so recursively make the parent and try again */ + char *slash = strrchr(path, '/'); + + if (slash && slash != path) { + *slash = 0; + if (mkdir_all(path) != 0) { + return -1; + } + *slash = '/'; + } + first: + if (MKDIR_DEFAULT(path) == 0) { + return 0; + } + if (errno == ENOENT) { + /* Create the parent and try again */ + continue; + } + /* Maybe it already exists as a directory */ + if (errno == EEXIST) { + struct stat sb; + + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + return 0; + } + /* Restore errno */ + errno = EEXIST; + } + /* Failed */ + break; + } + return -1; +} + +static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + while (argc--) { + char *path = Jim_StrDup(Jim_String(argv[0])); + int rc = mkdir_all(path); + + Jim_Free(path); + if (rc != 0) { + Jim_SetResultFormatted(interp, "can't create directory \"%#s\": %s", argv[0], + strerror(errno)); + return JIM_ERR; + } + argv++; + } + return JIM_OK; +} + +#ifdef HAVE_MKSTEMP +static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int fd; + char *filename; + const char *template = "/tmp/tcl.tmp.XXXXXX"; + + if (argc >= 1) { + template = Jim_String(argv[0]); + } + filename = Jim_StrDup(template); + + fd = mkstemp(filename); + if (fd < 0) { + Jim_SetResultString(interp, "Failed to create tempfile", -1); + return JIM_ERR; + } + close(fd); + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1)); + return JIM_OK; +} +#endif + +static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *source; + const char *dest; + int force = 0; + + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-force")) { + return -1; + } + force++; + argv++; + argc--; + } + + source = Jim_String(argv[0]); + dest = Jim_String(argv[1]); + + if (!force && access(dest, F_OK) == 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": target exists", argv[0], + argv[1]); + return JIM_ERR; + } + + if (rename(source, dest) != 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1], + strerror(errno)); + return JIM_ERR; + } + + return JIM_OK; +} + +static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (stat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +#ifndef HAVE_LSTAT +#define lstat stat +#endif + +static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (lstat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_atime); + return JIM_OK; +} + +static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (argc == 2) { +#ifdef HAVE_UTIMES + jim_wide newtime; + struct timeval times[2]; + + if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) { + return JIM_ERR; + } + + times[1].tv_sec = times[0].tv_sec = newtime; + times[1].tv_usec = times[0].tv_usec = 0; + + if (utimes(Jim_String(argv[0]), times) != 0) { + Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif + } + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_mtime); + return JIM_OK; +} + +static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_EvalPrefix(interp, "file copy", argc, argv); +} + +static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_size); + return JIM_OK; +} + +static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISDIR(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISREG(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +#ifdef HAVE_GETEUID +static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = (geteuid() == sb.st_uid); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} +#endif + +#if defined(HAVE_READLINK) +static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + char *linkValue = Jim_Alloc(MAXPATHLEN + 1); + + int linkLength = readlink(path, linkValue, MAXPATHLEN); + + if (linkLength == -1) { + Jim_Free(linkValue); + Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } + linkValue[linkLength] = 0; + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, linkValue, linkLength)); + return JIM_OK; +} +#endif + +static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); + return JIM_OK; +} + +static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argv[1], &sb); +} + +static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argv[1], &sb); +} + +static const jim_subcmd_type file_command_table[] = { + { .cmd = "atime", + .args = "name", + .function = file_cmd_atime, + .minargs = 1, + .maxargs = 1, + .description = "Last access time" + }, + { .cmd = "mtime", + .args = "name ?time?", + .function = file_cmd_mtime, + .minargs = 1, + .maxargs = 2, + .description = "Get or set last modification time" + }, + { .cmd = "copy", + .args = "?-force? source dest", + .function = file_cmd_copy, + .minargs = 2, + .maxargs = 3, + .description = "Copy source file to destination file" + }, + { .cmd = "dirname", + .args = "name", + .function = file_cmd_dirname, + .minargs = 1, + .maxargs = 1, + .description = "Directory part of the name" + }, + { .cmd = "rootname", + .args = "name", + .function = file_cmd_rootname, + .minargs = 1, + .maxargs = 1, + .description = "Name without any extension" + }, + { .cmd = "extension", + .args = "name", + .function = file_cmd_extension, + .minargs = 1, + .maxargs = 1, + .description = "Last extension including the dot" + }, + { .cmd = "tail", + .args = "name", + .function = file_cmd_tail, + .minargs = 1, + .maxargs = 1, + .description = "Last component of the name" + }, + { .cmd = "normalize", + .args = "name", + .function = file_cmd_normalize, + .minargs = 1, + .maxargs = 1, + .description = "Normalized path of name" + }, + { .cmd = "join", + .args = "name ?name ...?", + .function = file_cmd_join, + .minargs = 1, + .maxargs = -1, + .description = "Join multiple path components" + }, + { .cmd = "readable", + .args = "name", + .function = file_cmd_readable, + .minargs = 1, + .maxargs = 1, + .description = "Is file readable" + }, + { .cmd = "writable", + .args = "name", + .function = file_cmd_writable, + .minargs = 1, + .maxargs = 1, + .description = "Is file writable" + }, + { .cmd = "executable", + .args = "name", + .function = file_cmd_executable, + .minargs = 1, + .maxargs = 1, + .description = "Is file executable" + }, + { .cmd = "exists", + .args = "name", + .function = file_cmd_exists, + .minargs = 1, + .maxargs = 1, + .description = "Does file exist" + }, + { .cmd = "delete", + .args = "?-force|--? name ...", + .function = file_cmd_delete, + .minargs = 1, + .maxargs = -1, + .description = "Deletes the files or directories (must be empty unless -force)" + }, + { .cmd = "mkdir", + .args = "dir ...", + .function = file_cmd_mkdir, + .minargs = 1, + .maxargs = -1, + .description = "Creates the directories" + }, +#ifdef HAVE_MKSTEMP + { .cmd = "tempfile", + .args = "?template?", + .function = file_cmd_tempfile, + .minargs = 0, + .maxargs = 1, + .description = "Creates a temporary filename" + }, +#endif + { .cmd = "rename", + .args = "?-force? source dest", + .function = file_cmd_rename, + .minargs = 2, + .maxargs = 3, + .description = "Renames a file" + }, +#if defined(HAVE_READLINK) + { .cmd = "readlink", + .args = "name", + .function = file_cmd_readlink, + .minargs = 1, + .maxargs = 1, + .description = "Value of the symbolic link" + }, +#endif + { .cmd = "size", + .args = "name", + .function = file_cmd_size, + .minargs = 1, + .maxargs = 1, + .description = "Size of file" + }, + { .cmd = "stat", + .args = "name var", + .function = file_cmd_stat, + .minargs = 2, + .maxargs = 2, + .description = "Stores results of stat in var array" + }, + { .cmd = "lstat", + .args = "name var", + .function = file_cmd_lstat, + .minargs = 2, + .maxargs = 2, + .description = "Stores results of lstat in var array" + }, + { .cmd = "type", + .args = "name", + .function = file_cmd_type, + .minargs = 1, + .maxargs = 1, + .description = "Returns type of the file" + }, +#ifdef HAVE_GETEUID + { .cmd = "owned", + .args = "name", + .function = file_cmd_owned, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if owned by the current owner" + }, +#endif + { .cmd = "isdirectory", + .args = "name", + .function = file_cmd_isdirectory, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if name is a directory" + }, + { .cmd = "isfile", + .args = "name", + .function = file_cmd_isfile, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if name is a file" + }, + { + .cmd = 0 + } +}; + +static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "dirname"); + return JIM_ERR; + } + + path = Jim_String(argv[1]); + + if (chdir(path) != 0) { + Jim_SetResultFormatted(interp, "couldn't change working directory to \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const int cwd_len = 2048; + char *cwd = malloc(cwd_len); + + if (getcwd(cwd, cwd_len) == NULL) { + Jim_SetResultString(interp, "Failed to get pwd", -1); + return JIM_ERR; + } +#if defined(__MINGW32__) + { + /* Try to keep backlashes out of paths */ + char *p = cwd; + while ((p = strchr(p, '\\')) != NULL) { + *p++ = '/'; + } + } +#endif + + Jim_SetResultString(interp, cwd, -1); + + free(cwd); + return JIM_OK; +} + +int Jim_fileInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL); + Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); + Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-format.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-format.c new file mode 100755 index 0000000..c9cde89 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-format.c @@ -0,0 +1,433 @@ +/* + * Implements the internals of the format command for jim + * + * The FreeBSD license + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 8.5: + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1999 by Scriptics Corporation. + * + * See the file "tcl.license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +#include <ctype.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "utf8.h" + +#define JIM_UTF_MAX 3 +#define JIM_INTEGER_SPACE 24 +#define MAX_FLOAT_WIDTH 320 + +/** + * Apply the printf-like format in fmtObjPtr with the given arguments. + * + * Returns a new object with zero reference count if OK, or NULL on error. + */ +Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) +{ + const char *span, *format, *formatEnd, *msg; + int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; + static const char * const mixedXPG = + "cannot mix \"%\" and \"%n$\" conversion specifiers"; + static const char * const badIndex[2] = { + "not enough arguments for all format specifiers", + "\"%n$\" argument index out of range" + }; + int formatLen; + Jim_Obj *resultPtr; + + /* A single buffer is used to store numeric fields (with sprintf()) + * This buffer is allocated/reallocated as necessary + */ + char *num_buffer = NULL; + int num_buffer_size = 0; + + span = format = Jim_GetString(fmtObjPtr, &formatLen); + formatEnd = format + formatLen; + resultPtr = Jim_NewStringObj(interp, "", 0); + + while (format != formatEnd) { + char *end; + int gotMinus, sawFlag; + int gotPrecision, useShort; + long width, precision; + int newXpg; + int ch; + int step; + int doubleType; + char pad = ' '; + char spec[2*JIM_INTEGER_SPACE + 12]; + char *p; + + int formatted_chars; + int formatted_bytes; + const char *formatted_buf; + + step = utf8_tounicode(format, &ch); + format += step; + if (ch != '%') { + numBytes += step; + continue; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + numBytes = 0; + } + + /* + * Saw a % : process the format specifier. + * + * Step 0. Handle special case of escaped format marker (i.e., %%). + */ + + step = utf8_tounicode(format, &ch); + if (ch == '%') { + span = format; + numBytes = step; + format += step; + continue; + } + + /* + * Step 1. XPG3 position specifier + */ + + newXpg = 0; + if (isdigit(ch)) { + int position = strtoul(format, &end, 10); + if (*end == '$') { + newXpg = 1; + objIndex = position - 1; + format = end + 1; + step = utf8_tounicode(format, &ch); + } + } + if (newXpg) { + if (gotSequential) { + msg = mixedXPG; + goto errorMsg; + } + gotXpg = 1; + } else { + if (gotXpg) { + msg = mixedXPG; + goto errorMsg; + } + gotSequential = 1; + } + if ((objIndex < 0) || (objIndex >= objc)) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + + /* + * Step 2. Set of flags. Also build up the sprintf spec. + */ + p = spec; + *p++ = '%'; + + gotMinus = 0; + sawFlag = 1; + do { + switch (ch) { + case '-': + gotMinus = 1; + break; + case '0': + pad = ch; + break; + case ' ': + case '+': + case '#': + break; + default: + sawFlag = 0; + continue; + } + *p++ = ch; + format += step; + step = utf8_tounicode(format, &ch); + } while (sawFlag); + + /* + * Step 3. Minimum field width. + */ + + width = 0; + if (isdigit(ch)) { + width = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { + goto error; + } + if (width < 0) { + width = -width; + if (!gotMinus) { + *p++ = '-'; + gotMinus = 1; + } + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + /* + * Step 4. Precision. + */ + + gotPrecision = precision = 0; + if (ch == '.') { + gotPrecision = 1; + format += step; + step = utf8_tounicode(format, &ch); + } + if (isdigit(ch)) { + precision = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { + goto error; + } + + /* + * TODO: Check this truncation logic. + */ + + if (precision < 0) { + precision = 0; + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + /* + * Step 5. Length modifier. + */ + + useShort = 0; + if (ch == 'h') { + useShort = 1; + format += step; + step = utf8_tounicode(format, &ch); + } else if (ch == 'l') { + /* Just for compatibility. All non-short integers are wide. */ + format += step; + step = utf8_tounicode(format, &ch); + if (ch == 'l') { + format += step; + step = utf8_tounicode(format, &ch); + } + } + + format += step; + span = format; + + /* + * Step 6. The actual conversion character. + */ + + if (ch == 'i') { + ch = 'd'; + } + + doubleType = 0; + + /* Each valid conversion will set: + * formatted_buf - the result to be added + * formatted_chars - the length of formatted_buf in characters + * formatted_bytes - the length of formatted_buf in bytes + */ + switch (ch) { + case '\0': + msg = "format string ended in middle of field specifier"; + goto errorMsg; + case 's': { + formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); + formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); + if (gotPrecision && (precision < formatted_chars)) { + /* Need to build a (null terminated) truncated string */ + formatted_chars = precision; + formatted_bytes = utf8_index(formatted_buf, precision); + } + break; + } + case 'c': { + jim_wide code; + + if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { + goto error; + } + /* Just store the value in the 'spec' buffer */ + formatted_bytes = utf8_fromunicode(spec, code); + formatted_buf = spec; + formatted_chars = 1; + break; + } + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + doubleType = 1; + /* fall through */ + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': { + jim_wide w; + double d; + int length; + + /* Fill in the width and precision */ + if (width) { + p += sprintf(p, "%ld", width); + } + if (gotPrecision) { + p += sprintf(p, ".%ld", precision); + } + + /* Now the modifier, and get the actual value here */ + if (doubleType) { + if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { + goto error; + } + length = MAX_FLOAT_WIDTH; + } + else { + if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { + goto error; + } + length = JIM_INTEGER_SPACE; + if (useShort) { + *p++ = 'h'; + if (ch == 'd') { + w = (short)w; + } + else { + w = (unsigned short)w; + } + } + else { + *p++ = 'l'; +#ifdef HAVE_LONG_LONG + if (sizeof(long long) == sizeof(jim_wide)) { + *p++ = 'l'; + } +#endif + } + } + + *p++ = (char) ch; + *p = '\0'; + + /* Adjust length for width and precision */ + if (width > length) { + length = width; + } + if (gotPrecision) { + length += precision; + } + + /* Increase the size of the buffer if needed */ + if (num_buffer_size < length + 1) { + num_buffer_size = length + 1; + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); + } + + if (doubleType) { + snprintf(num_buffer, length + 1, spec, d); + } + else { + formatted_bytes = snprintf(num_buffer, length + 1, spec, w); + } + formatted_chars = formatted_bytes = strlen(num_buffer); + formatted_buf = num_buffer; + break; + } + + default: { + /* Just reuse the 'spec' buffer */ + spec[0] = ch; + spec[1] = '\0'; + Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); + goto error; + } + } + + if (!gotMinus) { + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + } + + Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); + + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + + objIndex += gotSequential; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + } + + Jim_Free(num_buffer); + return resultPtr; + + errorMsg: + Jim_SetResultString(interp, msg, -1); + error: + Jim_FreeNewObj(interp, resultPtr); + Jim_Free(num_buffer); + return NULL; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c new file mode 100755 index 0000000..658e8d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c @@ -0,0 +1,137 @@ +#include <errno.h> +#include <string.h> +#include "jim.h" +#include "jimautoconf.h" + +#ifdef USE_LINENOISE +#include <unistd.h> +#include "linenoise.h" +#else + +#define MAX_LINE_LEN 512 + +static char *linenoise(const char *prompt) +{ + char *line = malloc(MAX_LINE_LEN); + + fputs(prompt, stdout); + fflush(stdout); + + if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { + free(line); + return NULL; + } + return line; +} +#endif + +int Jim_InteractivePrompt(Jim_Interp *interp) +{ + int retcode = JIM_OK; + char *history_file = NULL; +#ifdef USE_LINENOISE + const char *home; + + home = getenv("HOME"); + if (home && isatty(STDIN_FILENO)) { + int history_len = strlen(home) + sizeof("/.jim_history"); + history_file = Jim_Alloc(history_len); + snprintf(history_file, history_len, "%s/.jim_history", home); + linenoiseHistoryLoad(history_file); + } +#endif + + printf("Welcome to Jim version %d.%d" JIM_NL, + JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); + + while (1) { + Jim_Obj *scriptObjPtr; + const char *result; + int reslen; + char prompt[20]; + const char *str; + + if (retcode != 0) { + const char *retcodestr = Jim_ReturnCode(retcode); + + if (*retcodestr == '?') { + snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode); + } + else { + snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr); + } + } + else { + prompt[0] = '\0'; + } + strcat(prompt, ". "); + + scriptObjPtr = Jim_NewStringObj(interp, "", 0); + Jim_IncrRefCount(scriptObjPtr); + while (1) { + char state; + int len; + char *line; + + line = linenoise(prompt); + if (line == NULL) { + if (errno == EINTR) { + continue; + } + Jim_DecrRefCount(interp, scriptObjPtr); + goto out; + } + if (Jim_Length(scriptObjPtr) != 0) { + Jim_AppendString(interp, scriptObjPtr, "\n", 1); + } + Jim_AppendString(interp, scriptObjPtr, line, -1); + free(line); + str = Jim_GetString(scriptObjPtr, &len); + if (len == 0) { + continue; + } + if (Jim_ScriptIsComplete(str, len, &state)) + break; + + snprintf(prompt, sizeof(prompt), "%c> ", state); + } +#ifdef USE_LINENOISE + if (strcmp(str, "h") == 0) { + /* built-in history command */ + int i; + int len; + char **history = linenoiseHistory(&len); + for (i = 0; i < len; i++) { + printf("%4d %s\n", i + 1, history[i]); + } + Jim_DecrRefCount(interp, scriptObjPtr); + continue; + } + + linenoiseHistoryAdd(Jim_String(scriptObjPtr)); + if (history_file) { + linenoiseHistorySave(history_file); + } +#endif + retcode = Jim_EvalObj(interp, scriptObjPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + + + + if (retcode == JIM_EXIT) { + Jim_Free(history_file); + return JIM_EXIT; + } + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + } + result = Jim_GetString(Jim_GetResult(interp), &reslen); + if (reslen) { + printf("%s\n", result); + } + } + out: + Jim_Free(history_file); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-load.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-load.c new file mode 100755 index 0000000..4dc6ed2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-load.c @@ -0,0 +1,126 @@ +#include "jim.h" +#include "jimautoconf.h" +#include <string.h> + +/* ----------------------------------------------------------------------------- + * Dynamic libraries support (WIN32 not supported) + * ---------------------------------------------------------------------------*/ + +#if defined(HAVE_DLOPEN) || defined(HAVE_DLOPEN_COMPAT) + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifndef RTLD_NOW + #define RTLD_NOW 0 +#endif +#ifndef RTLD_LOCAL + #define RTLD_LOCAL 0 +#endif + +/** + * Note that Jim_LoadLibrary() requires a path to an existing file. + * + * If it is necessary to search JIM_LIBPATH, use Jim_PackageRequire() instead. + */ +int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) +{ + void *handle = dlopen(pathName, RTLD_NOW | RTLD_LOCAL); + if (handle == NULL) { + Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName, + dlerror()); + } + else { + /* We use a unique init symbol depending on the extension name. + * This is done for compatibility between static and dynamic extensions. + * For extension readline.so, the init symbol is "Jim_readlineInit" + */ + const char *pt; + const char *pkgname; + int pkgnamelen; + char initsym[40]; + int (*onload) (Jim_Interp *); + + pt = strrchr(pathName, '/'); + if (pt) { + pkgname = pt + 1; + } + else { + pkgname = pathName; + } + pt = strchr(pkgname, '.'); + if (pt) { + pkgnamelen = pt - pkgname; + } + else { + pkgnamelen = strlen(pkgname); + } + snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname); + + if ((onload = dlsym(handle, initsym)) == NULL) { + Jim_SetResultFormatted(interp, + "No %s symbol found in extension %s", initsym, pathName); + } + else if (onload(interp) != JIM_ERR) { + /* Add this handle to the stack of handles to be freed */ + if (!interp->loadHandles) { + interp->loadHandles = Jim_Alloc(sizeof(*interp->loadHandles)); + Jim_InitStack(interp->loadHandles); + } + Jim_StackPush(interp->loadHandles, handle); + + Jim_SetEmptyResult(interp); + + return JIM_OK; + } + } + if (handle) { + dlclose(handle); + } + return JIM_ERR; +} + +static void JimFreeOneLoadHandle(void *handle) +{ + dlclose(handle); +} + +void Jim_FreeLoadHandles(Jim_Interp *interp) +{ + if (interp->loadHandles) { + Jim_FreeStackElements(interp->loadHandles, JimFreeOneLoadHandle); + Jim_Free(interp->loadHandles); + } +} + +#else /* JIM_DYNLIB */ +int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(pathName); + + Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1); + return JIM_ERR; +} + +void Jim_FreeLoadHandles(Jim_Interp *interp) +{ +} +#endif /* JIM_DYNLIB */ + +/* [load] */ +static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "libaryFile"); + return JIM_ERR; + } + return Jim_LoadLibrary(interp, Jim_String(argv[1])); +} + +int Jim_loadInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c new file mode 100755 index 0000000..be94f15 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c @@ -0,0 +1,338 @@ +#include <string.h> +#include <jim-nvp.h> + +int Jim_GetNvp(Jim_Interp *interp, + Jim_Obj *objPtr, const Jim_Nvp * nvp_table, const Jim_Nvp ** result) +{ + Jim_Nvp *n; + int e; + + e = Jim_Nvp_name2value_obj(interp, nvp_table, objPtr, &n); + if (e == JIM_ERR) { + return e; + } + + /* Success? found? */ + if (n->name) { + /* remove const */ + *result = (Jim_Nvp *) n; + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp * p, const char *name) +{ + while (p->name) { + if (0 == strcmp(name, p->name)) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + +Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp * p, const char *name) +{ + while (p->name) { + if (0 == strcasecmp(name, p->name)) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + +int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result) +{ + return Jim_Nvp_name2value(interp, p, Jim_String(o), result); +} + + +int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp * _p, const char *name, Jim_Nvp ** result) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_name2value_simple(_p, name); + + /* result */ + if (result) { + *result = (Jim_Nvp *) (p); + } + + /* found? */ + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +int +Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** puthere) +{ + return Jim_Nvp_name2value_nocase(interp, p, Jim_String(o), puthere); +} + +int +Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp * _p, const char *name, + Jim_Nvp ** puthere) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_name2value_nocase_simple(_p, name); + + if (puthere) { + *puthere = (Jim_Nvp *) (p); + } + /* found */ + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + + +int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result) +{ + int e;; + jim_wide w; + + e = Jim_GetWide(interp, o, &w); + if (e != JIM_OK) { + return e; + } + + return Jim_Nvp_value2name(interp, p, w, result); +} + +Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp * p, int value) +{ + while (p->name) { + if (value == p->value) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + + +int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp * _p, int value, Jim_Nvp ** result) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_value2name_simple(_p, value); + + if (result) { + *result = (Jim_Nvp *) (p); + } + + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + + +int Jim_GetOpt_Setup(Jim_GetOptInfo * p, Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + memset(p, 0, sizeof(*p)); + p->interp = interp; + p->argc = argc; + p->argv = argv; + + return JIM_OK; +} + +void Jim_GetOpt_Debug(Jim_GetOptInfo * p) +{ + int x; + + fprintf(stderr, "---args---\n"); + for (x = 0; x < p->argc; x++) { + fprintf(stderr, "%2d) %s\n", x, Jim_String(p->argv[x])); + } + fprintf(stderr, "-------\n"); +} + + +int Jim_GetOpt_Obj(Jim_GetOptInfo * goi, Jim_Obj **puthere) +{ + Jim_Obj *o; + + o = NULL; // failure + if (goi->argc) { + // success + o = goi->argv[0]; + goi->argc -= 1; + goi->argv += 1; + } + if (puthere) { + *puthere = o; + } + if (o != NULL) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +int Jim_GetOpt_String(Jim_GetOptInfo * goi, char **puthere, int *len) +{ + int r; + Jim_Obj *o; + const char *cp; + + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + cp = Jim_GetString(o, len); + if (puthere) { + /* remove const */ + *puthere = (char *)(cp); + } + } + return r; +} + +int Jim_GetOpt_Double(Jim_GetOptInfo * goi, double *puthere) +{ + int r; + Jim_Obj *o; + double _safe; + + if (puthere == NULL) { + puthere = &_safe; + } + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + r = Jim_GetDouble(goi->interp, o, puthere); + if (r != JIM_OK) { + Jim_SetResultFormatted(goi->interp, "not a number: %#s", o); + } + } + return r; +} + +int Jim_GetOpt_Wide(Jim_GetOptInfo * goi, jim_wide * puthere) +{ + int r; + Jim_Obj *o; + jim_wide _safe; + + if (puthere == NULL) { + puthere = &_safe; + } + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + r = Jim_GetWide(goi->interp, o, puthere); + } + return r; +} + +int Jim_GetOpt_Nvp(Jim_GetOptInfo * goi, const Jim_Nvp * nvp, Jim_Nvp ** puthere) +{ + Jim_Nvp *_safe; + Jim_Obj *o; + int e; + + if (puthere == NULL) { + puthere = &_safe; + } + + e = Jim_GetOpt_Obj(goi, &o); + if (e == JIM_OK) { + e = Jim_Nvp_name2value_obj(goi->interp, nvp, o, puthere); + } + + return e; +} + +void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo * goi, const Jim_Nvp * nvptable, int hadprefix) +{ + if (hadprefix) { + Jim_SetResult_NvpUnknown(goi->interp, goi->argv[-2], goi->argv[-1], nvptable); + } + else { + Jim_SetResult_NvpUnknown(goi->interp, NULL, goi->argv[-1], nvptable); + } +} + + +int Jim_GetOpt_Enum(Jim_GetOptInfo * goi, const char *const *lookup, int *puthere) +{ + int _safe; + Jim_Obj *o; + int e; + + if (puthere == NULL) { + puthere = &_safe; + } + e = Jim_GetOpt_Obj(goi, &o); + if (e == JIM_OK) { + e = Jim_GetEnum(goi->interp, o, lookup, puthere, "option", JIM_ERRMSG); + } + return e; +} + +void +Jim_SetResult_NvpUnknown(Jim_Interp *interp, + Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp * nvp) +{ + if (param_name) { + Jim_SetResultFormatted(interp, "%#s: Unknown: %#s, try one of: ", param_name, param_value); + } + else { + Jim_SetResultFormatted(interp, "Unknown param: %#s, try one of: ", param_value); + } + while (nvp->name) { + const char *a; + const char *b; + + if ((nvp + 1)->name) { + a = nvp->name; + b = ", "; + } + else { + a = "or "; + b = nvp->name; + } + Jim_AppendStrings(interp, Jim_GetResult(interp), a, b, NULL); + nvp++; + } +} + +const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static Jim_Obj *debug_string_obj; + + int x; + + if (debug_string_obj) { + Jim_FreeObj(interp, debug_string_obj); + } + + debug_string_obj = Jim_NewEmptyStringObj(interp); + for (x = 0; x < argc; x++) { + Jim_AppendStrings(interp, debug_string_obj, Jim_String(argv[x]), " ", NULL); + } + + return Jim_String(debug_string_obj); +} + +int Jim_nvpInit(Jim_Interp *interp) +{ + /* This is really a helper library, not an extension, but this is the easy way */ + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h new file mode 100755 index 0000000..12ff889 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h @@ -0,0 +1,275 @@ +#ifndef JIM_NVP_H +#define JIM_NVP_H + +#include <jim.h> + +/** Name Value Pairs, aka: NVP + * - Given a string - return the associated int. + * - Given a number - return the associated string. + * . + * + * Very useful when the number is not a simple index into an array of + * known string, or there may be multiple strings (aliases) that mean then same + * thing. + * + * An NVP Table is terminated with ".name = NULL". + * + * During the 'name2value' operation, if no matching string is found + * the pointer to the terminal element (with p->name == NULL) is returned. + * + * Example: + * \code + * const Jim_Nvp yn[] = { + * { "yes", 1 }, + * { "no" , 0 }, + * { "yep", 1 }, + * { "nope", 0 }, + * { NULL, -1 }, + * }; + * + * Jim_Nvp *result + * e = Jim_Nvp_name2value(interp, yn, "y", &result); + * returns &yn[0]; + * e = Jim_Nvp_name2value(interp, yn, "n", &result); + * returns &yn[1]; + * e = Jim_Nvp_name2value(interp, yn, "Blah", &result); + * returns &yn[4]; + * \endcode + * + * During the number2name operation, the first matching value is returned. + */ +typedef struct { + const char *name; + int value; +} Jim_Nvp; + + +int Jim_GetNvp (Jim_Interp *interp, + Jim_Obj *objPtr, + const Jim_Nvp *nvp_table, + const Jim_Nvp **result); + +/* Name Value Pairs Operations */ +Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *nvp_table, const char *name); +Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *nvp_table, const char *name); +Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *nvp_table, int v); + +int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); +int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); +int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *nvp_table, int value, Jim_Nvp **result); + +int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); +int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); +int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *value_obj, Jim_Nvp **result); + +/** prints a nice 'unknown' parameter error message to the 'result' */ +void Jim_SetResult_NvpUnknown(Jim_Interp *interp, + Jim_Obj *param_name, + Jim_Obj *param_value, + const Jim_Nvp *nvp_table); + + +/** Debug: convert argc/argv into a printable string for printf() debug + * + * \param interp - the interpeter + * \param argc - arg count + * \param argv - the objects + * + * \returns string pointer holding the text. + * + * Note, next call to this function will free the old (last) string. + * + * For example might want do this: + * \code + * fp = fopen("some.file.log", "a"); + * fprintf(fp, "PARAMS are: %s\n", Jim_DebugArgvString(interp, argc, argv)); + * fclose(fp); + * \endcode + */ +const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + + +/** A TCL -ish GetOpt like code. + * + * Some TCL objects have various "configuration" values. + * For example - in Tcl/Tk the "buttons" have many options. + * + * Usefull when dealing with command options. + * that may come in any order... + * + * Does not support "-foo = 123" type options. + * Only supports tcl type options, like "-foo 123" + */ + +typedef struct jim_getopt { + Jim_Interp *interp; + int argc; + Jim_Obj * const * argv; + int isconfigure; /* non-zero if configure */ +} Jim_GetOptInfo; + +/** GetOpt - how to. + * + * Example (short and incomplete): + * \code + * Jim_GetOptInfo goi; + * + * Jim_GetOpt_Setup(&goi, interp, argc, argv); + * + * while (goi.argc) { + * e = Jim_GetOpt_Nvp(&goi, nvp_options, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&goi, nvp_options, 0); + * return e; + * } + * + * switch (n->value) { + * case ALIVE: + * printf("Option ALIVE specified\n"); + * break; + * case FIRST: + * if (goi.argc < 1) { + * .. not enough args error .. + * } + * Jim_GetOpt_String(&goi, &cp, NULL); + * printf("FIRSTNAME: %s\n", cp); + * case AGE: + * Jim_GetOpt_Wide(&goi, &w); + * printf("AGE: %d\n", (int)(w)); + * break; + * case POLITICS: + * e = Jim_GetOpt_Nvp(&goi, nvp_politics, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&goi, nvp_politics, 1); + * return e; + * } + * } + * } + * + * \endcode + * + */ + +/** Setup GETOPT + * + * \param goi - get opt info to be initialized + * \param interp - jim interp + * \param argc - argc count. + * \param argv - argv (will be copied) + * + * \code + * Jim_GetOptInfo goi; + * + * Jim_GetOptSetup(&goi, interp, argc, argv); + * \endcode + */ + +int Jim_GetOpt_Setup(Jim_GetOptInfo *goi, + Jim_Interp *interp, + int argc, + Jim_Obj * const * argv); + + +/** Debug - Dump parameters to stderr + * \param goi - current parameters + */ +void Jim_GetOpt_Debug(Jim_GetOptInfo *goi); + + + +/** Remove argv[0] from the list. + * + * \param goi - get opt info + * \param puthere - where param is put + * + */ +int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere); + +/** Remove argv[0] as string. + * + * \param goi - get opt info + * \param puthere - where param is put + * \param len - return its length + */ +int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len); + +/** Remove argv[0] as double. + * + * \param goi - get opt info + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere); + +/** Remove argv[0] as wide. + * + * \param goi - get opt info + * \param puthere - where param is put. + */ +int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere); + +/** Remove argv[0] as NVP. + * + * \param goi - get opt info + * \param lookup - nvp lookup table + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, Jim_Nvp **puthere); + +/** Create an appropriate error message for an NVP. + * + * \param goi - options info + * \param lookup - the NVP table that was used. + * \param hadprefix - 0 or 1 if the option had a prefix. + * + * This function will set the "interp->result" to a human readable + * error message listing the available options. + * + * This function assumes the previous option argv[-1] is the unknown string. + * + * If this option had some prefix, then pass "hadprefix = 1" else pass "hadprefix = 0" + * + * Example: + * \code + * + * while (goi.argc) { + * // Get the next option + * e = Jim_GetOpt_Nvp(&goi, cmd_options, &n); + * if (e != JIM_OK) { + * // option was not recognized + * // pass 'hadprefix = 0' because there is no prefix + * Jim_GetOpt_NvpUnknown(&goi, cmd_options, 0); + * return e; + * } + * + * switch (n->value) { + * case OPT_SEX: + * // handle: --sex male | female | lots | needmore + * e = Jim_GetOpt_Nvp(&goi, &nvp_sex, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&ogi, nvp_sex, 1); + * return e; + * } + * printf("Code: (%d) is %s\n", n->value, n->name); + * break; + * case ...: + * [snip] + * } + * } + * \endcode + * + */ +void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadprefix); + + +/** Remove argv[0] as Enum + * + * \param goi - get opt info + * \param lookup - lookup table. + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char * const * lookup, int *puthere); + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-pack.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-pack.c new file mode 100755 index 0000000..88bf2c1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-pack.c @@ -0,0 +1,380 @@ +#include <string.h> +#include <jim.h> + +/* Provides the [pack] and [unpack] commands to pack and unpack + * a binary string to/from arbitrary width integers and strings. + * + * This may be used to implement the [binary] command. + */ + +/** + * Big endian bit test. + * + * Considers 'bitvect' as a big endian bit stream and returns + * bit 'b' as zero or non-zero. + */ +static int JimTestBitBigEndian(const unsigned char *bitvec, int b) +{ + div_t pos = div(b, 8); + return bitvec[pos.quot] & (1 << (7 - pos.rem)); +} + +/** + * Little endian bit test. + * + * Considers 'bitvect' as a little endian bit stream and returns + * bit 'b' as zero or non-zero. + */ +static int JimTestBitLittleEndian(const unsigned char *bitvec, int b) +{ + div_t pos = div(b, 8); + return bitvec[pos.quot] & (1 << pos.rem); +} + +/** + * Sign extends the given value, 'n' of width 'width' bits. + * + * For example, sign extending 0x80 with a width of 8, produces -128 + */ +static jim_wide JimSignExtend(jim_wide n, int width) +{ + if (width == sizeof(jim_wide) * 8) { + /* Can't sign extend the maximum size integer */ + return n; + } + if (n & ((jim_wide)1 << (width - 1))) { + /* Need to extend */ + n -= ((jim_wide)1 << width); + } + + return n; +} + +/** + * Big endian integer extraction. + * + * Considers 'bitvect' as a big endian bit stream. + * Returns an integer of the given width (in bits) + * starting at the given position (in bits). + * + * The pos/width must represent bits inside bitvec, + * and the width be no more than the width of jim_wide. + */ +static jim_wide JimBitIntBigEndian(const unsigned char *bitvec, int pos, int width) +{ + jim_wide result = 0; + int i; + + /* Aligned, byte extraction */ + if (pos % 8 == 0 && width % 8 == 0) { + for (i = 0; i < width; i += 8) { + result = (result << 8) + bitvec[(pos + i) / 8]; + } + return result; + } + + /* Unaligned */ + for (i = 0; i < width; i++) { + if (JimTestBitBigEndian(bitvec, pos + width - i - 1)) { + result |= ((jim_wide)1 << i); + } + } + + return result; +} + +/** + * Little endian integer extraction. + * + * Like JimBitIntBigEndian() but considers 'bitvect' as a little endian bit stream. + */ +static jim_wide JimBitIntLittleEndian(const unsigned char *bitvec, int pos, int width) +{ + jim_wide result = 0; + int i; + + /* Aligned, byte extraction */ + if (pos % 8 == 0 && width % 8 == 0) { + for (i = 0; i < width; i += 8) { + result += (jim_wide)bitvec[(pos + i) / 8] << i; + } + return result; + } + + /* Unaligned */ + for (i = 0; i < width; i++) { + if (JimTestBitLittleEndian(bitvec, pos + i)) { + result |= ((jim_wide)1 << i); + } + } + + return result; +} + +/** + * Big endian bit set. + * + * Considers 'bitvect' as a big endian bit stream and sets + * bit 'b' to 'bit' + */ +static void JimSetBitBigEndian(unsigned char *bitvec, int b, int bit) +{ + div_t pos = div(b, 8); + if (bit) { + bitvec[pos.quot] |= (1 << (7 - pos.rem)); + } + else { + bitvec[pos.quot] &= ~(1 << (7 - pos.rem)); + } +} + +/** + * Little endian bit set. + * + * Considers 'bitvect' as a little endian bit stream and sets + * bit 'b' to 'bit' + */ +static void JimSetBitLittleEndian(unsigned char *bitvec, int b, int bit) +{ + div_t pos = div(b, 8); + if (bit) { + bitvec[pos.quot] |= (1 << pos.rem); + } + else { + bitvec[pos.quot] &= ~(1 << pos.rem); + } +} + +/** + * Big endian integer packing. + * + * Considers 'bitvect' as a big endian bit stream. + * Packs integer 'value' of the given width (in bits) + * starting at the given position (in bits). + * + * The pos/width must represent bits inside bitvec, + * and the width be no more than the width of jim_wide. + */ +static void JimSetBitsIntBigEndian(unsigned char *bitvec, jim_wide value, int pos, int width) +{ + int i; + + /* Common fast option */ + if (pos % 8 == 0 && width == 8) { + bitvec[pos / 8] = value; + return; + } + + for (i = 0; i < width; i++) { + int bit = !!(value & ((jim_wide)1 << i)); + JimSetBitBigEndian(bitvec, pos + width - i - 1, bit); + } +} + +/** + * Little endian version of JimSetBitsIntBigEndian() + */ +static void JimSetBitsIntLittleEndian(unsigned char *bitvec, jim_wide value, int pos, int width) +{ + int i; + + /* Common fast option */ + if (pos % 8 == 0 && width == 8) { + bitvec[pos / 8] = value; + return; + } + + for (i = 0; i < width; i++) { + int bit = !!(value & ((jim_wide)1 << i)); + JimSetBitLittleEndian(bitvec, pos + i, bit); + } +} + +/** + * [unpack] + * + * Usage: unpack binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth + * + * Unpacks bits from $binvalue at bit position $bitpos and with $bitwidth. + * Interprets the value according to the type and returns it. + */ +static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int option; + static const char * const options[] = { "-intbe", "-intle", "-uintbe", "-uintle", "-str", NULL }; + enum { OPT_INTBE, OPT_INTLE, OPT_UINTBE, OPT_UINTLE, OPT_STR, }; + jim_wide pos; + jim_wide width; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_GetWide(interp, argv[3], &pos) != JIM_OK) { + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) { + return JIM_ERR; + } + + if (option == OPT_STR) { + int len; + const char *str = Jim_GetString(argv[1], &len); + + if (width % 8 || pos % 8) { + Jim_SetResultString(interp, "string field is not on a byte boundary", -1); + return JIM_ERR; + } + + if (pos >= 0 && width > 0 && pos < len * 8) { + if (pos + width > len * 8) { + width = len * 8 - pos; + } + Jim_SetResultString(interp, str + pos / 8, width / 8); + } + return JIM_OK; + } + else { + int len; + const unsigned char *str = (const unsigned char *)Jim_GetString(argv[1], &len); + jim_wide result = 0; + + if (width > sizeof(jim_wide) * 8) { + Jim_SetResultFormatted(interp, "int field is too wide: %#s", argv[4]); + return JIM_ERR; + } + + if (pos >= 0 && width > 0 && pos < len * 8) { + if (pos + width > len * 8) { + width = len * 8 - pos; + } + if (option == OPT_INTBE || option == OPT_UINTBE) { + result = JimBitIntBigEndian(str, pos, width); + } + else { + result = JimBitIntLittleEndian(str, pos, width); + } + if (option == OPT_INTBE || option == OPT_INTLE) { + result = JimSignExtend(result, width); + } + } + Jim_SetResultInt(interp, result); + return JIM_OK; + } +} + +/** + * [pack] + * + * Usage: pack varname value -intle|-intbe|-str width ?bitoffset? + * + * Packs the binary representation of 'value' into the variable of the given name. + * The value is packed according to the given type, width and bitoffset. + * The variable is created if necessary (like [append]) + * Ihe variable is expanded if necessary + */ +static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int option; + static const char * const options[] = { "-intle", "-intbe", "-str", NULL }; + enum { OPT_LE, OPT_BE, OPT_STR }; + jim_wide pos = 0; + jim_wide width; + jim_wide value; + Jim_Obj *stringObjPtr; + int len; + int freeobj = 0; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 1, argv, "varName value -intle|-intbe|-str bitwidth ?bitoffset?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[3], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + if (option != OPT_STR && Jim_GetWide(interp, argv[2], &value) != JIM_OK) { + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) { + return JIM_ERR; + } + if (width <= 0 || (option == OPT_STR && width % 8) || (option != OPT_STR && width > sizeof(jim_wide) * 8)) { + Jim_SetResultFormatted(interp, "bad bitwidth: %#s", argv[5]); + return JIM_ERR; + } + if (argc == 6) { + if (Jim_GetWide(interp, argv[5], &pos) != JIM_OK) { + return JIM_ERR; + } + if (pos < 0 || (option == OPT_STR && pos % 8)) { + Jim_SetResultFormatted(interp, "bad bitoffset: %#s", argv[5]); + return JIM_ERR; + } + } + + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!stringObjPtr) { + /* Create the string if it doesn't exist */ + stringObjPtr = Jim_NewEmptyStringObj(interp); + freeobj = 1; + } + else if (Jim_IsShared(stringObjPtr)) { + freeobj = 1; + stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); + } + + len = Jim_Length(stringObjPtr) * 8; + + /* Extend the string as necessary first */ + while (len < pos + width) { + Jim_AppendString(interp, stringObjPtr, "", 1); + len += 8; + } + + Jim_SetResultInt(interp, pos + width); + + /* Now set the bits. Note that the the string *must* have no non-string rep + * since we are writing the bytes directly. + */ + Jim_AppendString(interp, stringObjPtr, "", 0); + + if (option == OPT_BE) { + JimSetBitsIntBigEndian((unsigned char *)stringObjPtr->bytes, value, pos, width); + } + else if (option == OPT_LE) { + JimSetBitsIntLittleEndian((unsigned char *)stringObjPtr->bytes, value, pos, width); + } + else { + pos /= 8; + width /= 8; + + if (width > Jim_Length(argv[2])) { + width = Jim_Length(argv[2]); + } + memcpy(stringObjPtr->bytes + pos, Jim_GetString(argv[2], NULL), width); + /* No padding is needed since the string is already extended */ + } + + if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { + if (freeobj) { + Jim_FreeNewObj(interp, stringObjPtr); + return JIM_ERR; + } + } + return JIM_OK; +} + +int Jim_packInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "pack", "1.0", JIM_ERRMSG)) { + return JIM_ERR; + } + + Jim_CreateCommand(interp, "unpack", Jim_UnpackCmd, NULL, NULL); + Jim_CreateCommand(interp, "pack", Jim_PackCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-package.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-package.c new file mode 100755 index 0000000..9caec0d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-package.c @@ -0,0 +1,259 @@ +#include <unistd.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +/* ----------------------------------------------------------------------------- + * Packages handling + * ---------------------------------------------------------------------------*/ + +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) +{ + /* If the package was already provided returns an error. */ + Jim_HashEntry *he = Jim_FindHashEntry(&interp->packages, name); + + /* An empty result means the automatic entry. This can be replaced */ + if (he && *(const char *)he->u.val) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "package \"%s\" was already provided", name); + } + return JIM_ERR; + } + if (he) { + Jim_DeleteHashEntry(&interp->packages, name); + } + Jim_AddHashEntry(&interp->packages, name, (char *)ver); + return JIM_OK; +} + +static char *JimFindPackage(Jim_Interp *interp, char **prefixes, int prefixc, const char *pkgName) +{ + int i; + char *buf = Jim_Alloc(JIM_PATH_LEN); + + for (i = 0; i < prefixc; i++) { + if (prefixes[i] == NULL) + continue; + + /* Loadable modules are tried first */ +#ifdef jim_ext_load + snprintf(buf, JIM_PATH_LEN, "%s/%s.so", prefixes[i], pkgName); + if (access(buf, R_OK) == 0) { + return buf; + } +#endif + if (strcmp(prefixes[i], ".") == 0) { + snprintf(buf, JIM_PATH_LEN, "%s.tcl", pkgName); + } + else { + snprintf(buf, JIM_PATH_LEN, "%s/%s.tcl", prefixes[i], pkgName); + } + + if (access(buf, R_OK) == 0) { + return buf; + } + } + Jim_Free(buf); + return NULL; +} + +/* Search for a suitable package under every dir specified by JIM_LIBPATH, + * and load it if possible. If a suitable package was loaded with success + * JIM_OK is returned, otherwise JIM_ERR is returned. */ +static int JimLoadPackage(Jim_Interp *interp, const char *name, int flags) +{ + Jim_Obj *libPathObjPtr; + char **prefixes, *path; + int prefixc, i, retCode = JIM_ERR; + + libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE); + if (libPathObjPtr == NULL) { + prefixc = 0; + libPathObjPtr = NULL; + } + else { + Jim_IncrRefCount(libPathObjPtr); + prefixc = Jim_ListLength(interp, libPathObjPtr); + } + + prefixes = Jim_Alloc(sizeof(char *) * prefixc); + for (i = 0; i < prefixc; i++) { + Jim_Obj *prefixObjPtr; + + if (Jim_ListIndex(interp, libPathObjPtr, i, &prefixObjPtr, JIM_NONE) != JIM_OK) { + prefixes[i] = NULL; + continue; + } + prefixes[i] = Jim_StrDup(Jim_String(prefixObjPtr)); + } + + /* Scan every directory for the the first match */ + path = JimFindPackage(interp, prefixes, prefixc, name); + if (path != NULL) { + char *p = strrchr(path, '.'); + + /* Note: Even if the file fails to load, we consider the package loaded. + * This prevents issues with recursion. + * Use a dummy version of "" to signify this case. + */ + Jim_PackageProvide(interp, name, "", 0); + + /* Try to load/source it */ + if (p && strcmp(p, ".tcl") == 0) { + retCode = Jim_EvalFileGlobal(interp, path); + } +#ifdef jim_ext_load + else { + retCode = Jim_LoadLibrary(interp, path); + } +#endif + if (retCode != JIM_OK) { + /* Upon failure, remove the dummy entry */ + Jim_DeleteHashEntry(&interp->packages, name); + } + Jim_Free(path); + } + for (i = 0; i < prefixc; i++) + Jim_Free(prefixes[i]); + Jim_Free(prefixes); + if (libPathObjPtr) + Jim_DecrRefCount(interp, libPathObjPtr); + return retCode; +} + +int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags) +{ + Jim_HashEntry *he; + + /* Start with an empty error string */ + Jim_SetResultString(interp, "", 0); + + he = Jim_FindHashEntry(&interp->packages, name); + if (he == NULL) { + /* Try to load the package. */ + int retcode = JimLoadPackage(interp, name, flags); + if (retcode != JIM_OK) { + if (flags & JIM_ERRMSG) { + int len; + + Jim_GetString(Jim_GetResult(interp), &len); + Jim_SetResultFormatted(interp, "%#s%sCan't load package %s", + Jim_GetResult(interp), len ? "\n" : "", name); + } + return retcode; + } + + /* In case the package did no 'package provide' */ + Jim_PackageProvide(interp, name, "1.0", 0); + + /* Now it must exist */ + he = Jim_FindHashEntry(&interp->packages, name); + } + + Jim_SetResultString(interp, he->u.val, -1); + return JIM_OK; +} + +/* + *---------------------------------------------------------------------- + * + * package provide name ?version? + * + * This procedure is invoked to declare that a particular version + * of a particular package is now present in an interpreter. There + * must not be any other version of this package already + * provided in the interpreter. + * + * Results: + * Returns JIM_OK and sets the package version (or 1.0 if not specified). + * + *---------------------------------------------------------------------- + */ +static int package_cmd_provide(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *version = "1.0"; + + if (argc == 2) { + version = Jim_String(argv[1]); + } + return Jim_PackageProvide(interp, Jim_String(argv[0]), version, JIM_ERRMSG); +} + +/* + *---------------------------------------------------------------------- + * + * package require name ?version? + * + * This procedure is load a given package. + * Note that the version is ignored. + * + * Results: + * Returns JIM_OK and sets the package version. + * + *---------------------------------------------------------------------- + */ +static int package_cmd_require(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* package require failing is important enough to add to the stack */ + interp->addStackTrace++; + + return Jim_PackageRequire(interp, Jim_String(argv[0]), JIM_ERRMSG); +} + +/* + *---------------------------------------------------------------------- + * + * package list + * + * Returns a list of known packages + * + * Results: + * Returns JIM_OK and sets a list of known packages. + * + *---------------------------------------------------------------------- + */ +static int package_cmd_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + htiter = Jim_GetHashTableIterator(&interp->packages); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); + } + Jim_FreeHashTableIterator(htiter); + + Jim_SetResult(interp, listObjPtr); + + return JIM_OK; +} + +static const jim_subcmd_type package_command_table[] = { + {.cmd = "provide", + .args = "name ?version?", + .function = package_cmd_provide, + .minargs = 1, + .maxargs = 2, + .description = "Indicates that the current script provides the given package"}, + {.cmd = "require", + .args = "name ?version?", + .function = package_cmd_require, + .minargs = 1, + .maxargs = 2, + .description = "Loads the given package by looking in standard places"}, + {.cmd = "list", + .function = package_cmd_list, + .minargs = 0, + .maxargs = 0, + .description = "Lists all known packages"}, + {0} +}; + +int Jim_packageInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "package", Jim_SubCmdProc, (void *)package_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-posix.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-posix.c new file mode 100755 index 0000000..0cf3604 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-posix.c @@ -0,0 +1,231 @@ + +/* Jim - POSIX extension + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <errno.h> + +#include "jim.h" +#include "jimautoconf.h" + +#ifdef HAVE_SYS_SYSINFO_H +#include <sys/sysinfo.h> +#endif + +static void Jim_PosixSetError(Jim_Interp *interp) +{ + Jim_SetResultString(interp, strerror(errno), -1); +} + +#if defined(HAVE_FORK) +static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + pid_t pid; + + JIM_NOTUSED(argv); + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + if ((pid = fork()) == -1) { + Jim_PosixSetError(interp); + return JIM_ERR; + } + Jim_SetResultInt(interp, (jim_wide) pid); + return JIM_OK; +} +#endif + +/* + * os.wait ?-nohang? pid + * + * An interface to waitpid(2) + * + * Returns a 3 element list. + * + * If -nohang is specified, and the process is still alive, returns + * + * {0 none 0} + * + * If the process does not exist or has already been waited for, returns: + * + * {-1 error <error-description>} + * + * If the process exited normally, returns: + * + * {<pid> exit <exit-status>} + * + * If the process terminated on a signal, returns: + * + * {<pid> signal <signal-number>} + * + * Otherwise (core dump, stopped, continued, ...), returns: + * + * {<pid> other 0} + */ +static int Jim_PosixWaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int nohang = 0; + long pid; + int status; + Jim_Obj *listObj; + const char *type; + int value; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { + nohang = 1; + } + if (argc != nohang + 2) { + Jim_WrongNumArgs(interp, 1, argv, "?-nohang? pid"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) { + return JIM_ERR; + } + + pid = waitpid(pid, &status, nohang ? WNOHANG : 0); + listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pid)); + if (pid < 0) { + type = "error"; + value = errno; + } + else if (pid == 0) { + type = "none"; + value = 0; + } + else if (WIFEXITED(status)) { + type = "exit"; + value = WEXITSTATUS(status); + } + else if (WIFSIGNALED(status)) { + type = "signal"; + value = WTERMSIG(status); + } + else { + type = "other"; + value = 0; + } + + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, type, -1)); + if (pid < 0) { + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, strerror(value), -1)); + } + else { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); + } + Jim_SetResult(interp, listObj); + return JIM_OK; +} + +static int Jim_PosixGetidsCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objv[8]; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + objv[0] = Jim_NewStringObj(interp, "uid", -1); + objv[1] = Jim_NewIntObj(interp, getuid()); + objv[2] = Jim_NewStringObj(interp, "euid", -1); + objv[3] = Jim_NewIntObj(interp, geteuid()); + objv[4] = Jim_NewStringObj(interp, "gid", -1); + objv[5] = Jim_NewIntObj(interp, getgid()); + objv[6] = Jim_NewStringObj(interp, "egid", -1); + objv[7] = Jim_NewIntObj(interp, getegid()); + Jim_SetResult(interp, Jim_NewListObj(interp, objv, 8)); + return JIM_OK; +} + +#define JIM_HOST_NAME_MAX 1024 +static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *buf; + int rc = JIM_OK; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + buf = Jim_Alloc(JIM_HOST_NAME_MAX); + if (gethostname(buf, JIM_HOST_NAME_MAX) == -1) { + Jim_PosixSetError(interp); + rc = JIM_ERR; + } + else { + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, -1)); + } + return rc; +} + +static int Jim_PosixUptimeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_STRUCT_SYSINFO_UPTIME + struct sysinfo info; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + + if (sysinfo(&info) == -1) { + Jim_PosixSetError(interp); + return JIM_ERR; + } + + Jim_SetResultInt(interp, info.uptime); +#else + Jim_SetResultInt(interp, (long)time(NULL)); +#endif + return JIM_OK; +} + +static int Jim_PosixPidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + + Jim_SetResultInt(interp, getpid()); + return JIM_OK; +} + +int Jim_posixInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "posix", "1.0", JIM_ERRMSG)) + return JIM_ERR; + +#ifdef HAVE_FORK + Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); +#endif + Jim_CreateCommand(interp, "os.wait", Jim_PosixWaitCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.gethostname", Jim_PosixGethostnameCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.uptime", Jim_PosixUptimeCommand, NULL, NULL); + Jim_CreateCommand(interp, "pid", Jim_PosixPidCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c new file mode 100755 index 0000000..67fc956 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c @@ -0,0 +1,119 @@ + +/* + * Tcl readdir command. + * + * (c) 2008 Steve Bennett <steveb@worware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on original work by: + *----------------------------------------------------------------------------- + * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies. Karl Lehenbauer and + * Mark Diekhans make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + *----------------------------------------------------------------------------- + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <dirent.h> + +#include "jim.h" +#include "jimautoconf.h" + +/* + *----------------------------------------------------------------------------- + * + * Jim_ReaddirCmd -- + * Implements the rename TCL command: + * readdir ?-nocomplain? dirPath + * + * Results: + * Standard TCL result. + *----------------------------------------------------------------------------- + */ +int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *dirPath; + DIR *dirPtr; + struct dirent *entryPtr; + int nocomplain = 0; + + if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) { + nocomplain = 1; + } + if (argc != 2 && !nocomplain) { + Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath"); + return JIM_ERR; + } + + dirPath = Jim_String(argv[1 + nocomplain]); + + dirPtr = opendir(dirPath); + if (dirPtr == NULL) { + if (nocomplain) { + return JIM_OK; + } + Jim_SetResultString(interp, strerror(errno), -1); + return JIM_ERR; + } + Jim_SetResultString(interp, strerror(errno), -1); + + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + + while ((entryPtr = readdir(dirPtr)) != NULL) { + if (entryPtr->d_name[0] == '.') { + if (entryPtr->d_name[1] == '\0') { + continue; + } + if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) + continue; + } + Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, + entryPtr->d_name, -1)); + } + closedir(dirPtr); + + return JIM_OK; +} + +int Jim_readdirInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readline.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readline.c new file mode 100755 index 0000000..3990d0c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-readline.c @@ -0,0 +1,61 @@ + +/* Jim - Readline bindings for Jim + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jim.h" +#include "jimautoconf.h" + +#include <readline/readline.h> +#include <readline/history.h> + +static int JimRlReadlineCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *line; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "prompt"); + return JIM_ERR; + } + line = readline(Jim_String(argv[1])); + if (!line) { + return JIM_EXIT; + } + Jim_SetResult(interp, Jim_NewStringObj(interp, line, -1)); + return JIM_OK; +} + +static int JimRlAddHistoryCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "string"); + return JIM_ERR; + } + add_history(Jim_String(argv[1])); + return JIM_OK; +} + +int Jim_readlineInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "readline", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "readline.readline", JimRlReadlineCommand, NULL, NULL); + Jim_CreateCommand(interp, "readline.addhistory", JimRlAddHistoryCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c new file mode 100755 index 0000000..2ccd996 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c @@ -0,0 +1,566 @@ +/* + * Implements the regexp and regsub commands for Jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Uses C library regcomp()/regexec() for the matching. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jimregexp.h" + +static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + regfree(objPtr->internalRep.regexpValue.compre); + Jim_Free(objPtr->internalRep.regexpValue.compre); +} + +static const Jim_ObjType regexpObjType = { + "regexp", + FreeRegexpInternalRep, + NULL, + NULL, + JIM_TYPE_NONE +}; + +static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags) +{ + regex_t *compre; + const char *pattern; + int ret; + + /* Check if the object is already an uptodate variable */ + if (objPtr->typePtr == ®expObjType && + objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) { + /* nothing to do */ + return objPtr->internalRep.regexpValue.compre; + } + + /* Not a regexp or the flags do not match */ + + /* Get the string representation */ + pattern = Jim_String(objPtr); + compre = Jim_Alloc(sizeof(regex_t)); + + if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { + char buf[100]; + + regerror(ret, compre, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf); + regfree(compre); + Jim_Free(compre); + return NULL; + } + + Jim_FreeIntRep(interp, objPtr); + + objPtr->typePtr = ®expObjType; + objPtr->internalRep.regexpValue.flags = flags; + objPtr->internalRep.regexpValue.compre = compre; + + return compre; +} + +int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int opt_indices = 0; + int opt_all = 0; + int opt_inline = 0; + regex_t *regex; + int match, i, j; + int offset = 0; + regmatch_t *pmatch = NULL; + int source_len; + int result = JIM_OK; + const char *pattern; + const char *source_str; + int num_matches = 0; + int num_vars; + Jim_Obj *resultListObj = NULL; + int regcomp_flags = 0; + int eflags = 0; + int option; + enum { + OPT_INDICES, OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END + }; + static const char * const options[] = { + "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL + }; + + if (argc < 3) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_INDICES: + opt_indices = 1; + break; + + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_INLINE: + opt_inline = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i < 2) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + + pattern = Jim_String(argv[i]); + source_str = Jim_GetString(argv[i + 1], &source_len); + + num_vars = argc - i - 2; + + if (opt_inline) { + if (num_vars) { + Jim_SetResultString(interp, "regexp match variables not allowed when using -inline", + -1); + result = JIM_ERR; + goto done; + } + num_vars = regex->re_nsub + 1; + } + + pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch)); + + /* If an offset has been specified, adjust for that now. + * If it points past the end of the string, point to the terminating null + */ + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + source_str += source_len; + } + else if (offset > 0) { + source_str += offset; + } + eflags |= REG_NOTBOL; + } + + if (opt_inline) { + resultListObj = Jim_NewListObj(interp, NULL, 0); + } + + next_match: + match = regexec(regex, source_str, num_vars + 1, pmatch, eflags); + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + result = JIM_ERR; + goto done; + } + + if (match == REG_NOMATCH) { + goto done; + } + + num_matches++; + + if (opt_all && !opt_inline) { + /* Just count the number of matches, so skip the substitution h */ + goto try_next_match; + } + + /* + * If additional variable names have been specified, return + * index information in those variables. + */ + + j = 0; + for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) { + Jim_Obj *resultObj; + + if (opt_indices) { + resultObj = Jim_NewListObj(interp, NULL, 0); + } + else { + resultObj = Jim_NewStringObj(interp, "", 0); + } + + if (pmatch[j].rm_so == -1) { + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + } + } + else { + int len = pmatch[j].rm_eo - pmatch[j].rm_so; + + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so + len - 1)); + } + else { + Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len); + } + } + + if (opt_inline) { + Jim_ListAppendElement(interp, resultListObj, resultObj); + } + else { + /* And now set the result variable */ + result = Jim_SetVariable(interp, argv[i], resultObj); + + if (result != JIM_OK) { + Jim_FreeObj(interp, resultObj); + break; + } + } + } + + try_next_match: + if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) { + if (pmatch[0].rm_eo) { + offset += pmatch[0].rm_eo; + source_str += pmatch[0].rm_eo; + } + else { + source_str++; + offset++; + } + if (*source_str) { + eflags = REG_NOTBOL; + goto next_match; + } + } + + done: + if (result == JIM_OK) { + if (opt_inline) { + Jim_SetResult(interp, resultListObj); + } + else { + Jim_SetResultInt(interp, num_matches); + } + } + + Jim_Free(pmatch); + return result; +} + +#define MAX_SUB_MATCHES 50 + +int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int regcomp_flags = 0; + int regexec_flags = 0; + int opt_all = 0; + int offset = 0; + regex_t *regex; + const char *p; + int result; + regmatch_t pmatch[MAX_SUB_MATCHES + 1]; + int num_matches = 0; + + int i, j, n; + Jim_Obj *varname; + Jim_Obj *resultObj; + const char *source_str; + int source_len; + const char *replace_str; + int replace_len; + const char *pattern; + int option; + enum { + OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END + }; + static const char * const options[] = { + "-nocase", "-line", "-all", "-start", "--", NULL + }; + + if (argc < 4) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string subSpec ?varName?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i != 3 && argc - i != 4) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + pattern = Jim_String(argv[i]); + + source_str = Jim_GetString(argv[i + 1], &source_len); + replace_str = Jim_GetString(argv[i + 2], &replace_len); + varname = argv[i + 3]; + + /* Create the result string */ + resultObj = Jim_NewStringObj(interp, "", 0); + + /* If an offset has been specified, adjust for that now. + * If it points past the end of the string, point to the terminating null + */ + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + offset = source_len; + } + else if (offset < 0) { + offset = 0; + } + } + + /* Copy the part before -start */ + Jim_AppendString(interp, resultObj, source_str, offset); + + /* + * The following loop is to handle multiple matches within the + * same source string; each iteration handles one match and its + * corresponding substitution. If "-all" hasn't been specified + * then the loop body only gets executed once. + */ + + n = source_len - offset; + p = source_str + offset; + do { + int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags); + + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + return JIM_ERR; + } + if (match == REG_NOMATCH) { + break; + } + + num_matches++; + + /* + * Copy the portion of the source string before the match to the + * result variable. + */ + Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so); + + /* + * Append the subSpec (replace_str) argument to the variable, making appropriate + * substitutions. This code is a bit hairy because of the backslash + * conventions and because the code saves up ranges of characters in + * subSpec to reduce the number of calls to Jim_SetVar. + */ + + for (j = 0; j < replace_len; j++) { + int idx; + int c = replace_str[j]; + + if (c == '&') { + idx = 0; + } + else if (c == '\\' && j < replace_len) { + c = replace_str[++j]; + if ((c >= '0') && (c <= '9')) { + idx = c - '0'; + } + else if ((c == '\\') || (c == '&')) { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + else { + Jim_AppendString(interp, resultObj, replace_str + j - 1, 2); + continue; + } + } + else { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) { + Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so, + pmatch[idx].rm_eo - pmatch[idx].rm_so); + } + } + + p += pmatch[0].rm_eo; + n -= pmatch[0].rm_eo; + + /* If -all is not specified, or there is no source left, we are done */ + if (!opt_all || n == 0) { + break; + } + + /* An anchored pattern without -line must be done */ + if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { + break; + } + + /* If the pattern is empty, need to step forwards */ + if (pattern[0] == '\0' && n) { + /* Need to copy the char we are moving over */ + Jim_AppendString(interp, resultObj, p, 1); + p++; + n--; + } + + regexec_flags |= REG_NOTBOL; + } while (n); + + /* + * Copy the portion of the string after the last match to the + * result variable. + */ + Jim_AppendString(interp, resultObj, p, -1); + + /* And now set or return the result variable */ + if (argc - i == 4) { + result = Jim_SetVariable(interp, varname, resultObj); + + if (result == JIM_OK) { + Jim_SetResultInt(interp, num_matches); + } + else { + Jim_FreeObj(interp, resultObj); + } + } + else { + Jim_SetResult(interp, resultObj); + result = JIM_OK; + } + + return result; +} + +int Jim_regexpInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL); + Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c new file mode 100755 index 0000000..2e700eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c @@ -0,0 +1,234 @@ + +/* Jim - SDL extension + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <SDL/SDL.h> +#include <SDL/SDL_gfxPrimitives.h> + +#include "jim.h" +#include "jimautoconf.h" + +#define AIO_CMD_LEN 128 + +typedef struct JimSdlSurface +{ + SDL_Surface *screen; +} JimSdlSurface; + +static void JimSdlSetError(Jim_Interp *interp) +{ + Jim_SetResultString(interp, SDL_GetError(), -1); +} + +static void JimSdlDelProc(Jim_Interp *interp, void *privData) +{ + JimSdlSurface *jss = privData; + + JIM_NOTUSED(interp); + + SDL_FreeSurface(jss->screen); + Jim_Free(jss); +} + +/* Calls to commands created via [sdl.surface] are implemented by this + * C command. */ +static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + int option; + static const char * const options[] = { + "free", "flip", "pixel", "rectangle", "box", "line", "aaline", + "circle", "aacircle", "fcircle", NULL + }; + enum + { OPT_FREE, OPT_FLIP, OPT_PIXEL, OPT_RECTANGLE, OPT_BOX, OPT_LINE, + OPT_AALINE, OPT_CIRCLE, OPT_AACIRCLE, OPT_FCIRCLE + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, "SDL surface method", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + if (option == OPT_PIXEL) { + /* PIXEL */ + long x, y, red, green, blue, alpha = 255; + + if (argc != 7 && argc != 8) { + Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || + Jim_GetLong(interp, argv[3], &y) != JIM_OK || + Jim_GetLong(interp, argv[4], &red) != JIM_OK || + Jim_GetLong(interp, argv[5], &green) != JIM_OK || + Jim_GetLong(interp, argv[6], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 8 && Jim_GetLong(interp, argv[7], &alpha) != JIM_OK) + return JIM_ERR; + pixelRGBA(jss->screen, x, y, red, green, blue, alpha); + return JIM_OK; + } + else if (option == OPT_RECTANGLE || option == OPT_BOX || + option == OPT_LINE || option == OPT_AALINE) { + /* RECTANGLE, BOX, LINE, AALINE */ + long x1, y1, x2, y2, red, green, blue, alpha = 255; + + if (argc != 9 && argc != 10) { + Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x1) != JIM_OK || + Jim_GetLong(interp, argv[3], &y1) != JIM_OK || + Jim_GetLong(interp, argv[4], &x2) != JIM_OK || + Jim_GetLong(interp, argv[5], &y2) != JIM_OK || + Jim_GetLong(interp, argv[6], &red) != JIM_OK || + Jim_GetLong(interp, argv[7], &green) != JIM_OK || + Jim_GetLong(interp, argv[8], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 10 && Jim_GetLong(interp, argv[9], &alpha) != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_RECTANGLE: + rectangleRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_BOX: + boxRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_LINE: + lineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_AALINE: + aalineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + } + return JIM_OK; + } + else if (option == OPT_CIRCLE || option == OPT_AACIRCLE || option == OPT_FCIRCLE) { + /* CIRCLE, AACIRCLE, FCIRCLE */ + long x, y, radius, red, green, blue, alpha = 255; + + if (argc != 8 && argc != 9) { + Jim_WrongNumArgs(interp, 2, argv, "x y radius red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || + Jim_GetLong(interp, argv[3], &y) != JIM_OK || + Jim_GetLong(interp, argv[4], &radius) != JIM_OK || + Jim_GetLong(interp, argv[5], &red) != JIM_OK || + Jim_GetLong(interp, argv[6], &green) != JIM_OK || + Jim_GetLong(interp, argv[7], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 9 && Jim_GetLong(interp, argv[8], &alpha) != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_CIRCLE: + circleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + case OPT_AACIRCLE: + aacircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + case OPT_FCIRCLE: + filledCircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + } + return JIM_OK; + } + else if (option == OPT_FREE) { + /* FREE */ + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + Jim_DeleteCommand(interp, Jim_String(argv[0])); + return JIM_OK; + } + else if (option == OPT_FLIP) { + /* FLIP */ + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + SDL_Flip(jss->screen); + return JIM_OK; + } + return JIM_OK; +} + +static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss; + char buf[AIO_CMD_LEN]; + Jim_Obj *objPtr; + long screenId, xres, yres; + SDL_Surface *screen; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "xres yres"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK || + Jim_GetLong(interp, argv[2], &yres) != JIM_OK) + return JIM_ERR; + + /* Try to create the surface */ + screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT); + if (screen == NULL) { + JimSdlSetError(interp); + return JIM_ERR; + } + /* Get the next file id */ + if (Jim_EvalGlobal(interp, "if {[catch {incr sdl.surfaceId}]} {set sdl.surfaceId 0}") != JIM_OK) + return JIM_ERR; + objPtr = Jim_GetVariableStr(interp, "sdl.surfaceId", JIM_ERRMSG); + if (objPtr == NULL) + return JIM_ERR; + if (Jim_GetLong(interp, objPtr, &screenId) != JIM_OK) + return JIM_ERR; + + /* Create the SDL screen command */ + jss = Jim_Alloc(sizeof(*jss)); + jss->screen = screen; + sprintf(buf, "sdl.surface%ld", screenId); + Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; +} + +int Jim_sdlInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + JimSdlSetError(interp); + return JIM_ERR; + } + atexit(SDL_Quit); + Jim_CreateCommand(interp, "sdl.screen", JimSdlSurfaceCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.c new file mode 100755 index 0000000..6a2a2be --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.c @@ -0,0 +1,514 @@ + +/* + * jim-signal.c + * + */ + +#include <signal.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" +#include "jim-signal.h" + +#define MAX_SIGNALS (sizeof(jim_wide) * 8) + +static jim_wide *sigloc; +static jim_wide sigsblocked; +static struct sigaction *sa_old; +static int signal_handling[MAX_SIGNALS]; + +/* Make sure to do this as a wide, not int */ +#define sig_to_bit(SIG) ((jim_wide)1 << (SIG)) + +static void signal_handler(int sig) +{ + /* We just remember which signals occurred. Jim_Eval() will + * notice this as soon as it can and throw an error + */ + *sigloc |= sig_to_bit(sig); +} + +static void signal_ignorer(int sig) +{ + /* We just remember which signals occurred */ + sigsblocked |= sig_to_bit(sig); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SignalId -- + * + * Return a textual identifier for a signal number. + * + * Results: + * This procedure returns a machine-readable textual identifier + * that corresponds to sig. The identifier is the same as the + * #define name in signal.h. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +#define CHECK_SIG(NAME) if (sig == NAME) return #NAME + +const char *Jim_SignalId(int sig) +{ + CHECK_SIG(SIGABRT); + CHECK_SIG(SIGALRM); + CHECK_SIG(SIGBUS); + CHECK_SIG(SIGCHLD); + CHECK_SIG(SIGCONT); + CHECK_SIG(SIGFPE); + CHECK_SIG(SIGHUP); + CHECK_SIG(SIGILL); + CHECK_SIG(SIGINT); +#ifdef SIGIO + CHECK_SIG(SIGIO); +#endif + CHECK_SIG(SIGKILL); + CHECK_SIG(SIGPIPE); + CHECK_SIG(SIGPROF); + CHECK_SIG(SIGQUIT); + CHECK_SIG(SIGSEGV); + CHECK_SIG(SIGSTOP); + CHECK_SIG(SIGSYS); + CHECK_SIG(SIGTERM); + CHECK_SIG(SIGTRAP); + CHECK_SIG(SIGTSTP); + CHECK_SIG(SIGTTIN); + CHECK_SIG(SIGTTOU); + CHECK_SIG(SIGURG); + CHECK_SIG(SIGUSR1); + CHECK_SIG(SIGUSR2); + CHECK_SIG(SIGVTALRM); + CHECK_SIG(SIGWINCH); + CHECK_SIG(SIGXCPU); + CHECK_SIG(SIGXFSZ); +#ifdef SIGPWR + CHECK_SIG(SIGPWR); +#endif +#ifdef SIGCLD + CHECK_SIG(SIGCLD); +#endif +#ifdef SIGEMT + CHECK_SIG(SIGEMT); +#endif +#ifdef SIGLOST + CHECK_SIG(SIGLOST); +#endif +#ifdef SIGPOLL + CHECK_SIG(SIGPOLL); +#endif +#ifdef SIGINFO + CHECK_SIG(SIGINFO); +#endif + return "unknown signal"; +} + +const char *Jim_SignalName(int sig) +{ +#ifdef HAVE_SYS_SIGLIST + if (sig >= 0 && sig < NSIG) { + return sys_siglist[sig]; + } +#endif + return Jim_SignalId(sig); +} + +/** + * Given the name of a signal, returns the signal value if found, + * or returns -1 (and sets an error) if not found. + * We accept -SIGINT, SIGINT, INT or any lowercase version or a number, + * either positive or negative. + */ +static int find_signal_by_name(Jim_Interp *interp, const char *name) +{ + int i; + const char *pt = name; + + /* Remove optional - and SIG from the front of the name */ + if (*pt == '-') { + pt++; + } + if (strncasecmp(name, "sig", 3) == 0) { + pt += 3; + } + if (isdigit(UCHAR(pt[0]))) { + i = atoi(pt); + if (i > 0 && i < MAX_SIGNALS) { + return i; + } + } + else { + for (i = 1; i < MAX_SIGNALS; i++) { + /* Jim_SignalId() returns names such as SIGINT, and + * returns "unknown signal id" if unknown, so this will work + */ + if (strcasecmp(Jim_SignalId(i) + 3, pt) == 0) { + return i; + } + } + } + Jim_SetResultString(interp, "unknown signal ", -1); + Jim_AppendString(interp, Jim_GetResult(interp), name, -1); + + return -1; +} + +#define SIGNAL_ACTION_HANDLE 1 +#define SIGNAL_ACTION_IGNORE -1 +#define SIGNAL_ACTION_DEFAULT 0 + +static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *const *argv) +{ + struct sigaction sa; + int i; + + if (argc == 0) { + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (i = 1; i < MAX_SIGNALS; i++) { + if (signal_handling[i] == action) { + /* Add signal name to the list */ + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, Jim_SignalId(i), -1)); + } + } + return JIM_OK; + } + + /* Catch all the signals we care about */ + if (action != SIGNAL_ACTION_DEFAULT) { + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (action == SIGNAL_ACTION_HANDLE) { + sa.sa_handler = signal_handler; + } + else { + sa.sa_handler = signal_ignorer; + } + } + + /* Iterate through the provided signals */ + for (i = 0; i < argc; i++) { + int sig = find_signal_by_name(interp, Jim_String(argv[i])); + + if (sig < 0) { + return JIM_ERR; + } + if (action != signal_handling[sig]) { + /* Need to change the action for this signal */ + switch (action) { + case SIGNAL_ACTION_HANDLE: + case SIGNAL_ACTION_IGNORE: + if (signal_handling[sig] == SIGNAL_ACTION_DEFAULT) { + if (!sa_old) { + /* Allocate the structure the first time through */ + sa_old = Jim_Alloc(sizeof(*sa_old) * MAX_SIGNALS); + } + sigaction(sig, &sa, &sa_old[sig]); + } + else { + sigaction(sig, &sa, 0); + } + break; + + case SIGNAL_ACTION_DEFAULT: + /* Restore old handler */ + if (sa_old) { + sigaction(sig, &sa_old[sig], 0); + } + } + signal_handling[sig] = action; + } + } + + return JIM_OK; +} + +static int signal_cmd_handle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_HANDLE, argc, argv); +} + +static int signal_cmd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_IGNORE, argc, argv); +} + +static int signal_cmd_default(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_DEFAULT, argc, argv); +} + +static int signal_set_sigmask_result(Jim_Interp *interp, jim_wide sigmask) +{ + int i; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < MAX_SIGNALS; i++) { + if (sigmask & sig_to_bit(i)) { + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, Jim_SignalId(i), -1)); + } + } + Jim_SetResult(interp, listObj); + return JIM_OK; +} + +static int signal_cmd_check(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int clear = 0; + jim_wide mask = 0; + jim_wide blocked; + + if (argc > 0 && Jim_CompareStringImmediate(interp, argv[0], "-clear")) { + clear++; + } + if (argc > clear) { + int i; + + /* Signals specified */ + for (i = clear; i < argc; i++) { + int sig = find_signal_by_name(interp, Jim_String(argv[i])); + + if (sig < 0 || sig >= MAX_SIGNALS) { + return -1; + } + mask |= sig_to_bit(sig); + } + } + else { + /* No signals specified, so check/clear all */ + mask = ~mask; + } + + if ((sigsblocked & mask) == 0) { + /* No matching signals, so empty result and nothing to do */ + return JIM_OK; + } + /* Be careful we don't have a race condition where signals are cleared but not returned */ + blocked = sigsblocked & mask; + if (clear) { + sigsblocked &= ~blocked; + } + /* Set the result */ + signal_set_sigmask_result(interp, blocked); + return JIM_OK; +} + +static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig = SIGINT; + + if (argc == 1) { + if ((sig = find_signal_by_name(interp, Jim_String(argv[0]))) < 0) { + return JIM_ERR; + } + } + + /* If the signal is ignored (blocked) ... */ + if (signal_handling[sig] == SIGNAL_ACTION_IGNORE) { + sigsblocked |= sig_to_bit(sig); + return JIM_OK; + } + + /* Just set the signal */ + interp->sigmask |= sig_to_bit(sig); + + /* Set the canonical name of the signal as the result */ + Jim_SetResultString(interp, Jim_SignalId(sig), -1); + + /* And simply say we caught the signal */ + return JIM_SIGNAL; +} + +/* + *----------------------------------------------------------------------------- + * + * Jim_SignalCmd -- + * Implements the TCL signal command: + * signal handle|ignore|default|throw ?signals ...? + * signal throw signal + * + * Specifies which signals are handled by Tcl code. + * If the one of the given signals is caught, it causes a JIM_SIGNAL + * exception to be thrown which can be caught by catch. + * + * Use 'signal ignore' to ignore the signal(s) + * Use 'signal default' to go back to the default behaviour + * Use 'signal throw signal' to raise the given signal + * + * If no arguments are given, returns the list of signals which are being handled + * + * Results: + * Standard TCL results. + * + *----------------------------------------------------------------------------- + */ +static const jim_subcmd_type signal_command_table[] = { + { .cmd = "handle", + .args = "?signals ...?", + .function = signal_cmd_handle, + .minargs = 0, + .maxargs = -1, + .description = "Lists handled signals, or adds to handled signals" + }, + { .cmd = "ignore", + .args = "?signals ...?", + .function = signal_cmd_ignore, + .minargs = 0, + .maxargs = -1, + .description = "Lists ignored signals, or adds to ignored signals" + }, + { .cmd = "default", + .args = "?signals ...?", + .function = signal_cmd_default, + .minargs = 0, + .maxargs = -1, + .description = "Lists defaulted signals, or adds to defaulted signals" + }, + { .cmd = "check", + .args = "?-clear? ?signals ...?", + .function = signal_cmd_check, + .minargs = 0, + .maxargs = -1, + .description = "Returns ignored signals which have occurred, and optionally clearing them" + }, + { .cmd = "throw", + .args = "?signal?", + .function = signal_cmd_throw, + .minargs = 0, + .maxargs = 1, + .description = "Raises the given signal (default SIGINT)" + }, + { 0 } +}; + +static int Jim_AlarmCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { +#ifdef HAVE_UALARM + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { + if (t < 1) { + ualarm(t * 1e6, 0); + } + else { + alarm(t); + } + } +#else + long t; + + ret = Jim_GetLong(interp, argv[1], &t); + if (ret == JIM_OK) { + alarm(t); + } +#endif + } + + return ret; +} + +static int Jim_SleepCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { +#ifdef HAVE_USLEEP + if (t < 1) { + usleep(t * 1e6); + } + else +#endif + sleep(t); + } + } + + return ret; +} + +static int Jim_KillCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig; + long pid; + Jim_Obj *pidObj; + const char *signame; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?SIG|-0? pid"); + return JIM_ERR; + } + + if (argc == 2) { + signame = "SIGTERM"; + pidObj = argv[1]; + } + else { + signame = Jim_String(argv[1]); + pidObj = argv[2]; + } + + /* Special 'kill -0 pid' to determine if a pid exists */ + if (strcmp(signame, "-0") == 0 || strcmp(signame, "0") == 0) { + sig = 0; + } + else { + sig = find_signal_by_name(interp, signame); + if (sig < 0) { + return JIM_ERR; + } + } + + if (Jim_GetLong(interp, pidObj, &pid) != JIM_OK) { + return JIM_ERR; + } + + if (kill(pid, sig) == 0) { + return JIM_OK; + } + + Jim_SetResultString(interp, "kill: Failed to deliver signal", -1); + return JIM_ERR; +} + +int Jim_signalInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "signal", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + /* Teach the jim core how to set a result from a sigmask */ + interp->signal_set_result = signal_set_sigmask_result; + + /* Make sure we know where to store the signals which occur */ + sigloc = &interp->sigmask; + + Jim_CreateCommand(interp, "signal", Jim_SubCmdProc, (void *)signal_command_table, NULL); + Jim_CreateCommand(interp, "alarm", Jim_AlarmCmd, 0, 0); + Jim_CreateCommand(interp, "kill", Jim_KillCmd, 0, 0); + + /* Sleep is slightly dubious here */ + Jim_CreateCommand(interp, "sleep", Jim_SleepCmd, 0, 0); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.h new file mode 100755 index 0000000..92e080d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-signal.h @@ -0,0 +1,24 @@ +#ifndef JIM_SIGNAL_H +#define JIM_SIGNAL_H + +/* + *---------------------------------------------------------------------- + * + * Tcl_SignalId -- + * + * Return a textual identifier for a signal number. + * + * Results: + * This procedure returns a machine-readable textual identifier + * that corresponds to sig. The identifier is the same as the + * #define name in signal.h. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +const char *Jim_SignalId(int sig); +const char *Jim_SignalName(int sig); + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c new file mode 100755 index 0000000..2de560a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c @@ -0,0 +1,293 @@ +#include <stdio.h> +#include <string.h> + +#include "jim-subcmd.h" +#include "jimautoconf.h" + +/** + * Implements the common 'commands' subcommand + */ +static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* Nothing to do, since the result has already been created */ + return JIM_OK; +} + +/** + * Do-nothing command to support -commands and -usage + */ +static const jim_subcmd_type dummy_subcmd = { + .cmd = "dummy", + .function = subcmd_null, + .flags = JIM_MODFLAG_HIDDEN, +}; + +static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep) +{ + const char *s = ""; + + for (; ct->cmd; ct++) { + if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { + Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL); + s = sep; + } + } +} + +static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, + Jim_Obj *cmd, Jim_Obj *subcmd) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type, + " command \"", Jim_String(subcmd), "\": should be ", NULL); + add_commands(interp, command_table, ", "); +} + +static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, + Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), + " command ... \", where command is one of: ", NULL); + add_commands(interp, command_table, ", "); +} + +static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) +{ + if (cmd) { + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL); + if (ct->args && *ct->args) { + Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL); + } +} + +static void show_full_usage(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, + Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + for (; ct->cmd; ct++) { + if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + if (ct->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n ", ct->description, NULL); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", NULL); + } + } +} + +static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) +{ + Jim_SetResultString(interp, "wrong # args: must be \"", -1); + add_cmd_usage(interp, command_table, subcmd); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); +} + +const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, + int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct; + const jim_subcmd_type *partial = 0; + int cmdlen; + Jim_Obj *cmd; + const char *cmdstr; + const char *cmdname; + int help = 0; + + cmdname = Jim_String(argv[0]); + + if (argc < 2) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, + " command ...\"\n", NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help\" or \"", + cmdname, " -help command\" for help", NULL); + return 0; + } + + cmd = argv[1]; + + if (argc == 2 && Jim_CompareStringImmediate(interp, cmd, "-usage")) { + /* Show full usage */ + show_full_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + + /* Check for the help command */ + if (Jim_CompareStringImmediate(interp, cmd, "-help")) { + if (argc == 2) { + /* Usage for the command, not the subcommand */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + help = 1; + + /* Skip the 'help' command */ + cmd = argv[2]; + } + + /* Check for special builtin '-commands' command first */ + if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { + /* Build the result here */ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + add_commands(interp, command_table, " "); + return &dummy_subcmd; + } + + cmdstr = Jim_GetString(cmd, &cmdlen); + + for (ct = command_table; ct->cmd; ct++) { + if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { + /* Found an exact match */ + break; + } + if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { + if (partial) { + /* Ambiguous */ + if (help) { + /* Just show the top level help here */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); + return 0; + } + partial = ct; + } + continue; + } + + /* If we had an unambiguous partial match */ + if (partial && !ct->cmd) { + ct = partial; + } + + if (!ct->cmd) { + /* No matching command */ + if (help) { + /* Just show the top level help here */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); + return 0; + } + + if (help) { + Jim_SetResultString(interp, "Usage: ", -1); + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + if (ct->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", ct->description, NULL); + } + return &dummy_subcmd; + } + + /* Check the number of args */ + if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { + Jim_SetResultString(interp, "wrong # args: must be \"", -1); + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); + + return 0; + } + + /* Good command */ + return ct; +} + +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) +{ + int ret = JIM_ERR; + + if (ct) { + if (ct->flags & JIM_MODFLAG_FULLARGV) { + ret = ct->function(interp, argc, argv); + } + else { + ret = ct->function(interp, argc - 2, argv + 2); + } + if (ret < 0) { + set_wrong_args(interp, ct, argv[0]); + ret = JIM_ERR; + } + } + return ret; +} + +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct = + Jim_ParseSubCmd(interp, (const jim_subcmd_type *)Jim_CmdPrivData(interp), argc, argv); + + return Jim_CallSubCmd(interp, ct, argc, argv); +} + +/* The following two functions are for normal commands */ +int +Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, + Jim_Obj *const *argv) +{ + /* -usage or -help */ + if (argc == 2) { + if (Jim_CompareStringImmediate(interp, argv[1], "-usage") + || Jim_CompareStringImmediate(interp, argv[1], "-help")) { + Jim_SetResultString(interp, "Usage: ", -1); + add_cmd_usage(interp, command_table, NULL); + if (command_table->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", command_table->description, + NULL); + } + return JIM_OK; + } + } + if (argc >= 2 && command_table->function) { + /* This is actually a sub command table */ + + Jim_Obj *nargv[4]; + int nargc = 0; + const char *subcmd = NULL; + + if (Jim_CompareStringImmediate(interp, argv[1], "-subcommands")) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + add_commands(interp, (jim_subcmd_type *) command_table->function, " "); + return JIM_OK; + } + + if (Jim_CompareStringImmediate(interp, argv[1], "-subhelp") + || Jim_CompareStringImmediate(interp, argv[1], "-help")) { + subcmd = "-help"; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "-subusage")) { + subcmd = "-usage"; + } + + if (subcmd) { + nargv[nargc++] = Jim_NewStringObj(interp, "$handle", -1); + nargv[nargc++] = Jim_NewStringObj(interp, subcmd, -1); + if (argc >= 3) { + nargv[nargc++] = argv[2]; + } + Jim_ParseSubCmd(interp, (jim_subcmd_type *) command_table->function, nargc, nargv); + Jim_FreeNewObj(interp, nargv[0]); + Jim_FreeNewObj(interp, nargv[1]); + return 0; + } + } + + /* Check the number of args */ + if (argc - 1 < command_table->minargs || (command_table->maxargs >= 0 + && argc - 1 > command_table->maxargs)) { + set_wrong_args(interp, command_table, NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\nUse \"", Jim_String(argv[0]), + " -help\" for help", NULL); + return JIM_ERR; + } + + /* Not usage, but passed arg checking */ + return -1; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h new file mode 100755 index 0000000..3a672eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h @@ -0,0 +1,92 @@ +/* Provides a common approach to implementing Tcl commands + * which implement subcommands + */ +#ifndef JIM_SUBCMD_H +#define JIM_SUBCMD_H + +#include <jim.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +#define JIM_MODFLAG_HIDDEN 0x0001 /* Don't show the subcommand in usage or commands */ +#define JIM_MODFLAG_FULLARGV 0x0002 /* Subcmd proc gets called with full argv */ + +/* Custom flags start at 0x0100 */ + +/** + * Returns JIM_OK if OK, JIM_ERR (etc.) on error, break, continue, etc. + * Returns -1 if invalid args. + */ +typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +typedef struct { + const char *cmd; /* Name of the (sub)command */ + const char *args; /* Textual description of allowed args */ + tclmod_cmd_function *function; /* Function implementing the subcommand */ + short minargs; /* Minimum required arguments */ + short maxargs; /* Maximum allowed arguments or -1 if no limit */ + unsigned flags; /* JIM_MODFLAG_... plus custom flags */ + const char *description; /* Description of the subcommand */ +} jim_subcmd_type; + +/** + * Looks up the appropriate subcommand in the given command table and return + * the command function which implements the subcommand. + * NULL will be returned and an appropriate error will be set if the subcommand or + * arguments are invalid. + * + * Typical usage is: + * { + * const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, command_table, argc, argv); + * + * return Jim_CallSubCmd(interp, ct, argc, argv); + * } + * + */ +const jim_subcmd_type * +Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); + +/** + * Parses the args against the given command table and executes the subcommand if found + * or sets an appropriate error if the subcommand or arguments is invalid. + * + * Can be used directly with Jim_CreateCommand() where the ClientData is the command table. + * + * e.g. Jim_CreateCommand(interp, "mycmd", Jim_SubCmdProc, command_table, NULL); + */ +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +/** + * Invokes the given subcmd with the given args as returned + * by Jim_ParseSubCmd() + * + * If ct is NULL, returns JIM_ERR, leaving any message. + * Otherwise invokes ct->function + * + * If ct->function returns -1, sets an error message and returns JIM_ERR. + * Otherwise returns the result of ct->function. + */ +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv); + +/** + * Standard processing for a command. + * + * This does the '-help' and '-usage' check and the number of args checks. + * for a top level command against a single 'jim_subcmd_type' structure. + * + * Additionally, if command_table->function is set, it should point to a sub command table + * and '-subhelp ?subcmd?', '-subusage' and '-subcommands' are then also recognised. + * + * Returns 0 if user requested usage, -1 on arg error, 1 if OK to process. + */ +int +Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c new file mode 100755 index 0000000..4e14910 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c @@ -0,0 +1,190 @@ + +/* Syslog interface for tcl + * Copyright Victor Wagner <vitus@ice.ru> at + * http://www.ice.ru/~vitus/works/tcl.html#syslog + * + * Slightly modified by Steve Bennett <steveb@snapgear.com> + * Ported to Jim by Steve Bennett <steveb@workware.net.au> + */ +#include <syslog.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" + +typedef struct +{ + int logOpened; + int facility; + int options; + char ident[32]; +} SyslogInfo; + +#ifndef LOG_AUTHPRIV +# define LOG_AUTHPRIV LOG_AUTH +#endif + +static const char * const facilities[] = { + [LOG_AUTHPRIV] = "authpriv", + [LOG_CRON] = "cron", + [LOG_DAEMON] = "daemon", + [LOG_KERN] = "kernel", + [LOG_LPR] = "lpr", + [LOG_MAIL] = "mail", + [LOG_NEWS] = "news", + [LOG_SYSLOG] = "syslog", + [LOG_USER] = "user", + [LOG_UUCP] = "uucp", + [LOG_LOCAL0] = "local0", + [LOG_LOCAL1] = "local1", + [LOG_LOCAL2] = "local2", + [LOG_LOCAL3] = "local3", + [LOG_LOCAL4] = "local4", + [LOG_LOCAL5] = "local5", + [LOG_LOCAL6] = "local6", + [LOG_LOCAL7] = "local7", +}; + +static const char * const priorities[] = { + [LOG_EMERG] = "emerg", + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_ERR] = "error", + [LOG_WARNING] = "warning", + [LOG_NOTICE] = "notice", + [LOG_INFO] = "info", + [LOG_DEBUG] = "debug", +}; + +/** + * Deletes the syslog command. + */ +static void Jim_SyslogCmdDelete(Jim_Interp *interp, void *privData) +{ + SyslogInfo *info = (SyslogInfo *) privData; + + if (info->logOpened) { + closelog(); + } + Jim_Free(info); +} + +/* Syslog_Log - + * implements syslog tcl command. General format: syslog ?options? level text + * options -facility -ident -options + * + * syslog ?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? text + */ +int Jim_SyslogCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int priority = LOG_INFO; + int i = 1; + SyslogInfo *info = Jim_CmdPrivData(interp); + + if (argc <= 1) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? message"); + return JIM_ERR; + } + while (i < argc - 1) { + if (Jim_CompareStringImmediate(interp, argv[i], "-facility")) { + int entry = + Jim_FindByName(Jim_String(argv[i + 1]), facilities, + sizeof(facilities) / sizeof(*facilities)); + if (entry < 0) { + Jim_SetResultString(interp, "Unknown facility", -1); + return JIM_ERR; + } + if (info->facility != entry) { + info->facility = entry; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-options")) { + long tmp; + + if (Jim_GetLong(interp, argv[i + 1], &tmp) == JIM_ERR) { + return JIM_ERR; + } + info->options = tmp; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-ident")) { + strncpy(info->ident, Jim_String(argv[i + 1]), sizeof(info->ident)); + info->ident[sizeof(info->ident) - 1] = 0; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + else { + break; + } + i += 2; + } + + /* There should be either 0, 1 or 2 args left */ + if (i == argc) { + /* No args, but they have set some options, so OK */ + return JIM_OK; + } + + if (i < argc - 1) { + priority = + Jim_FindByName(Jim_String(argv[i]), priorities, + sizeof(priorities) / sizeof(*priorities)); + if (priority < 0) { + Jim_SetResultString(interp, "Unknown priority", -1); + return JIM_ERR; + } + i++; + } + + if (i != argc - 1) { + goto wrongargs; + } + if (!info->logOpened) { + if (!info->ident[0]) { + Jim_Obj *argv0 = Jim_GetGlobalVariableStr(interp, "argv0", JIM_NONE); + + if (argv0) { + strncpy(info->ident, Jim_String(argv0), sizeof(info->ident)); + } + else { + strcpy(info->ident, "Tcl script"); + } + info->ident[sizeof(info->ident) - 1] = 0; + } + openlog(info->ident, info->options, info->facility); + info->logOpened = 1; + } + syslog(priority, "%s", Jim_String(argv[i])); + + return JIM_OK; +} + +int Jim_syslogInit(Jim_Interp *interp) +{ + SyslogInfo *info; + + if (Jim_PackageProvide(interp, "syslog", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + info = Jim_Alloc(sizeof(*info)); + + info->logOpened = 0; + info->options = 0; + info->facility = LOG_USER; + info->ident[0] = 0; + + Jim_CreateCommand(interp, "syslog", Jim_SyslogCmd, info, Jim_SyslogCmdDelete); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h new file mode 100755 index 0000000..89e01f5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h @@ -0,0 +1,69 @@ +#ifndef JIM_WIN32COMPAT_H +#define JIM_WIN32COMPAT_H + +/* Compatibility for Windows (mingw and msvc, not cygwin */ + +/* Note that at this point we don't yet have access to jimautoconf.h */ +#if defined(_WIN32) || defined(WIN32) +#ifndef STRICT + #define STRICT +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define HAVE_DLOPEN +void *dlopen(const char *path, int mode); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); +char *dlerror(void); + +#ifdef _MSC_VER +/* These are msvc vs gcc */ + +#if _MSC_VER >= 1000 + #pragma warning(disable:4146) +#endif + +#define strcasecmp _stricmp + +#define jim_wide _int64 +#ifndef LLONG_MAX + #define LLONG_MAX 9223372036854775807I64 +#endif +#ifndef LLONG_MIN + #define LLONG_MIN (-LLONG_MAX - 1I64) +#endif +#define JIM_WIDE_MIN LLONG_MIN +#define JIM_WIDE_MAX LLONG_MAX +#define JIM_WIDE_MODIFIER "I64d" + +#include <io.h> + +#define HAVE_GETTIMEOFDAY +struct timeval { + long tv_sec; + long tv_usec; +}; + +int gettimeofday(struct timeval *tv, void *unused); + +#define HAVE_OPENDIR +struct dirent { + char *d_name; +}; + +typedef struct DIR { + long handle; /* -1 for failed rewind */ + struct _finddata_t info; + struct dirent result; /* d_name null iff first time */ + char *name; /* null-terminated char string */ +} DIR; + +DIR *opendir(const char *name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); +#endif /* _MSC_VER */ + +#endif /* WIN32 */ + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jim.c new file mode 100755 index 0000000..8543de4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim.c @@ -0,0 +1,14478 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008,2009 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ +#define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */ + +#include <stdio.h> +#include <stdlib.h> + +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> +#include <assert.h> +#include <errno.h> +#include <time.h> +#include <setjmp.h> + +#include <unistd.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "utf8.h" + +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif +#ifdef HAVE_CRT_EXTERNS_H +#include <crt_externs.h> +#endif + +/* For INFINITY, even if math functions are not enabled */ +#include <math.h> + +/* We may decide to switch to using $[...] after all, so leave it as an option */ +/*#define EXPRSUGAR_BRACKET*/ + +/* For the no-autoconf case */ +#ifndef TCL_LIBRARY +#define TCL_LIBRARY "." +#endif +#ifndef TCL_PLATFORM_OS +#define TCL_PLATFORM_OS "unknown" +#endif +#ifndef TCL_PLATFORM_PLATFORM +#define TCL_PLATFORM_PLATFORM "unknown" +#endif +#ifndef TCL_PLATFORM_PATH_SEPARATOR +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#endif + +/*#define DEBUG_SHOW_SCRIPT*/ +/*#define DEBUG_SHOW_SCRIPT_TOKENS*/ +/*#define DEBUG_SHOW_SUBST*/ +/*#define DEBUG_SHOW_EXPR*/ +/*#define DEBUG_SHOW_EXPR_TOKENS*/ +/*#define JIM_DEBUG_GC*/ +#ifdef JIM_MAINTAINER +#define JIM_DEBUG_COMMAND +#define JIM_DEBUG_PANIC +#endif + +const char *jim_tt_name(int type); + +#ifdef JIM_DEBUG_PANIC +static void JimPanicDump(int panic_condition, const char *fmt, ...); +#define JimPanic(X) JimPanicDump X +#else +#define JimPanic(X) +#endif + +/* ----------------------------------------------------------------------------- + * Global variables + * ---------------------------------------------------------------------------*/ + +/* A shared empty string for the objects string representation. + * Jim_InvalidateStringRep knows about it and doesn't try to free it. */ +static char JimEmptyStringRep[] = ""; + +/* ----------------------------------------------------------------------------- + * Required prototypes of not exported functions + * ---------------------------------------------------------------------------*/ +static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, + int flags); +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name); +static void JimDeleteLocalProcs(Jim_Interp *interp); +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, + int argc, Jim_Obj *const *argv); +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, + Jim_Obj *fileNameObj, int linenr); +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); +static int JimSign(jim_wide w); +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len); + + +static const Jim_HashTableType JimVariablesHashTableType; + +/* Fast access to the int (wide) value of an object which is known to be of int type */ +#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue + +#define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none") + +static int utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + +/* These can be used in addition to JIM_CASESENS/JIM_NOCASE */ +#define JIM_CHARSET_SCAN 2 +#define JIM_CHARSET_GLOB 0 + +/** + * pattern points to a string like "[^a-z\ub5]" + * + * The pattern may contain trailing chars, which are ignored. + * + * The pattern is matched against unicode char 'c'. + * + * If (flags & JIM_NOCASE), case is ignored when matching. + * If (flags & JIM_CHARSET_SCAN), the considers ^ and ] special at the start + * of the charset, per scan, rather than glob/string match. + * + * If the unicode char 'c' matches that set, returns a pointer to the ']' character, + * or the null character if the ']' is missing. + * + * Returns NULL on no match. + */ +static const char *JimCharsetMatch(const char *pattern, int c, int flags) +{ + int not = 0; + int pchar; + int match = 0; + int nocase = 0; + + if (flags & JIM_NOCASE) { + nocase++; + c = utf8_upper(c); + } + + if (flags & JIM_CHARSET_SCAN) { + if (*pattern == '^') { + not++; + pattern++; + } + + /* Special case. If the first char is ']', it is part of the set */ + if (*pattern == ']') { + goto first; + } + } + + while (*pattern && *pattern != ']') { + /* Exact match */ + if (pattern[0] == '\\') { +first: + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + } + else { + /* Is this a range? a-z */ + int start; + int end; + + pattern += utf8_tounicode_case(pattern, &start, nocase); + if (pattern[0] == '-' && pattern[1]) { + /* skip '-' */ + pattern += utf8_tounicode(pattern, &pchar); + pattern += utf8_tounicode_case(pattern, &end, nocase); + + /* Handle reversed range too */ + if ((c >= start && c <= end) || (c >= end && c <= start)) { + match = 1; + } + continue; + } + pchar = start; + } + + if (pchar == c) { + match = 1; + } + } + if (not) { + match = !match; + } + + return match ? pattern : NULL; +} + +/* Glob-style pattern matching. */ + +/* Note: string *must* be valid UTF-8 sequences + * slen is a char length, not byte counts. + */ +static int GlobMatch(const char *pattern, const char *string, int nocase) +{ + int c; + int pchar; + while (*pattern) { + switch (pattern[0]) { + case '*': + while (pattern[1] == '*') { + pattern++; + } + pattern++; + if (!pattern[0]) { + return 1; /* match */ + } + while (*string) { + /* Recursive call - Does the remaining pattern match anywhere? */ + if (GlobMatch(pattern, string, nocase)) + return 1; /* match */ + string += utf8_tounicode(string, &c); + } + return 0; /* no match */ + + case '?': + string += utf8_tounicode(string, &c); + break; + + case '[': { + string += utf8_tounicode(string, &c); + pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); + if (!pattern) { + return 0; + } + if (!*pattern) { + /* Ran out of pattern (no ']') */ + continue; + } + break; + } + case '\\': + if (pattern[1]) { + pattern++; + } + /* fall through */ + default: + string += utf8_tounicode_case(string, &c, nocase); + utf8_tounicode_case(pattern, &pchar, nocase); + if (pchar != c) { + return 0; + } + break; + } + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + if (!*string) { + while (*pattern == '*') { + pattern++; + } + break; + } + } + if (!*pattern && !*string) { + return 1; + } + return 0; +} + +static int JimStringMatch(Jim_Interp *interp, Jim_Obj *patternObj, const char *string, int nocase) +{ + return GlobMatch(Jim_String(patternObj), string, nocase); +} + +/** + * string comparison works on binary data. + * + * Note that the lengths are byte lengths, not char lengths. + */ +static int JimStringCompare(const char *s1, int l1, const char *s2, int l2) +{ + if (l1 < l2) { + return memcmp(s1, s2, l1) <= 0 ? -1 : 1; + } + else if (l2 < l1) { + return memcmp(s1, s2, l2) >= 0 ? 1 : -1; + } + else { + return JimSign(memcmp(s1, s2, l1)); + } +} + +/** + * No-case version. + * + * If maxchars is -1, compares to end of string. + * Otherwise compares at most 'maxchars' characters. + */ +static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars) +{ + while (*s1 && *s2 && maxchars) { + int c1, c2; + s1 += utf8_tounicode_case(s1, &c1, 1); + s2 += utf8_tounicode_case(s2, &c2, 1); + if (c1 != c2) { + return JimSign(c1 - c2); + } + maxchars--; + } + if (!maxchars) { + return 0; + } + /* One string or both terminated */ + if (*s1) { + return 1; + } + if (*s2) { + return -1; + } + return 0; +} + +/* Search 's1' inside 's2', starting to search from char 'index' of 's2'. + * The index of the first occurrence of s1 in s2 is returned. + * If s1 is not found inside s2, -1 is returned. */ +static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx) +{ + int i; + int l1bytelen; + + if (!l1 || !l2 || l1 > l2) { + return -1; + } + if (idx < 0) + idx = 0; + s2 += utf8_index(s2, idx); + + l1bytelen = utf8_index(s1, l1); + + for (i = idx; i <= l2 - l1; i++) { + int c; + if (memcmp(s2, s1, l1bytelen) == 0) { + return i; + } + s2 += utf8_tounicode(s2, &c); + } + return -1; +} + +/** + * Note: Lengths and return value are in bytes, not chars. + */ +static int JimStringLast(const char *s1, int l1, const char *s2, int l2) +{ + const char *p; + + if (!l1 || !l2 || l1 > l2) + return -1; + + /* Now search for the needle */ + for (p = s2 + l2 - 1; p != s2 - 1; p--) { + if (*p == *s1 && memcmp(s1, p, l1) == 0) { + return p - s2; + } + } + return -1; +} + +#ifdef JIM_UTF8 +/** + * Note: Lengths and return value are in chars. + */ +static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2) +{ + int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2)); + if (n > 0) { + n = utf8_strlen(s2, n); + } + return n; +} +#endif + +int Jim_WideToString(char *buf, jim_wide wideValue) +{ + const char *fmt = "%" JIM_WIDE_MODIFIER; + + return sprintf(buf, fmt, wideValue); +} + +/** + * After an strtol()/strtod()-like conversion, + * check whether something was converted and that + * the only thing left is white space. + * + * Returns JIM_OK or JIM_ERR. + */ +static int JimCheckConversion(const char *str, const char *endptr) +{ + if (str[0] == '\0' || str == endptr) { + return JIM_ERR; + } + + if (endptr[0] != '\0') { + while (*endptr) { + if (!isspace(UCHAR(*endptr))) { + return JIM_ERR; + } + endptr++; + } + } + return JIM_OK; +} + +int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) +{ + char *endptr; + + *widePtr = strtoull(str, &endptr, base); + + return JimCheckConversion(str, endptr); +} + +int Jim_DoubleToString(char *buf, double doubleValue) +{ + int len; + char *buf0 = buf; + + len = sprintf(buf, "%.12g", doubleValue); + + /* Add a final ".0" if it's a number. But not + * for NaN or InF */ + while (*buf) { + if (*buf == '.' || isalpha(UCHAR(*buf))) { + /* inf -> Inf, nan -> Nan */ + if (*buf == 'i' || *buf == 'n') { + *buf = toupper(UCHAR(*buf)); + } + if (*buf == 'I') { + /* Infinity -> Inf */ + buf[3] = '\0'; + len = buf - buf0 + 3; + } + return len; + } + buf++; + } + + *buf++ = '.'; + *buf++ = '0'; + *buf = '\0'; + + return len + 2; +} + +int Jim_StringToDouble(const char *str, double *doublePtr) +{ + char *endptr; + + /* Callers can check for underflow via ERANGE */ + errno = 0; + + *doublePtr = strtod(str, &endptr); + + return JimCheckConversion(str, endptr); +} + +static jim_wide JimPowWide(jim_wide b, jim_wide e) +{ + jim_wide i, res = 1; + + if ((b == 0 && e != 0) || (e < 0)) + return 0; + for (i = 0; i < e; i++) { + res *= b; + } + return res; +} + +/* ----------------------------------------------------------------------------- + * Special functions + * ---------------------------------------------------------------------------*/ +#ifdef JIM_DEBUG_PANIC +void JimPanicDump(int condition, const char *fmt, ...) +{ + va_list ap; + + if (!condition) { + return; + } + + va_start(ap, fmt); + + fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, JIM_NL JIM_NL); + va_end(ap); + +#ifdef HAVE_BACKTRACE + { + void *array[40]; + int size, i; + char **strings; + + size = backtrace(array, 40); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]); + fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL); + fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL); + } +#endif + + abort(); +} +#endif + +/* ----------------------------------------------------------------------------- + * Memory allocation + * ---------------------------------------------------------------------------*/ + +void *Jim_Alloc(int size) +{ + return malloc(size); +} + +void Jim_Free(void *ptr) +{ + free(ptr); +} + +void *Jim_Realloc(void *ptr, int size) +{ + return realloc(ptr, size); +} + +char *Jim_StrDup(const char *s) +{ + return strdup(s); +} + +char *Jim_StrDupLen(const char *s, int l) +{ + char *copy = Jim_Alloc(l + 1); + + memcpy(copy, s, l + 1); + copy[l] = 0; /* Just to be sure, original could be substring */ + return copy; +} + +/* ----------------------------------------------------------------------------- + * Time related functions + * ---------------------------------------------------------------------------*/ + +/* Returns microseconds of CPU used since start. */ +static jim_wide JimClock(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec; +} + +/* ----------------------------------------------------------------------------- + * Hash Tables + * ---------------------------------------------------------------------------*/ + +/* -------------------------- private prototypes ---------------------------- */ +static int JimExpandHashTableIfNeeded(Jim_HashTable *ht); +static unsigned int JimHashTableNextPower(unsigned int size); +static int JimInsertHashEntry(Jim_HashTable *ht, const void *key); + +/* -------------------------- hash functions -------------------------------- */ + +/* Thomas Wang's 32 bit Mix Function */ +unsigned int Jim_IntHashFunction(unsigned int key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} + +/* Generic hash function (we are using to multiply by 9 and add the byte + * as Tcl) */ +unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) +{ + unsigned int h = 0; + + while (len--) + h += (h << 3) + *buf++; + return h; +} + +/* ----------------------------- API implementation ------------------------- */ + +/* reset a hashtable already initialized with ht_init(). + * NOTE: This function should only called by ht_destroy(). */ +static void JimResetHashTable(Jim_HashTable *ht) +{ + ht->table = NULL; + ht->size = 0; + ht->sizemask = 0; + ht->used = 0; + ht->collisions = 0; +} + +/* Initialize the hash table */ +int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) +{ + JimResetHashTable(ht); + ht->type = type; + ht->privdata = privDataPtr; + return JIM_OK; +} + +/* Resize the table to the minimal size that contains all the elements, + * but with the invariant of a USER/BUCKETS ration near to <= 1 */ +int Jim_ResizeHashTable(Jim_HashTable *ht) +{ + int minimal = ht->used; + + if (minimal < JIM_HT_INITIAL_SIZE) + minimal = JIM_HT_INITIAL_SIZE; + return Jim_ExpandHashTable(ht, minimal); +} + +/* Expand or create the hashtable */ +int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) +{ + Jim_HashTable n; /* the new hashtable */ + unsigned int realsize = JimHashTableNextPower(size), i; + + /* the size is invalid if it is smaller than the number of + * elements already inside the hashtable */ + if (ht->used >= size) + return JIM_ERR; + + Jim_InitHashTable(&n, ht->type, ht->privdata); + n.size = realsize; + n.sizemask = realsize - 1; + n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); + + /* Initialize all the pointers to NULL */ + memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); + + /* Copy all the elements from the old to the new table: + * note that if the old hash table is empty ht->used is zero, + * so Jim_ExpandHashTable just creates an empty hash table. */ + n.used = ht->used; + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if (ht->table[i] == NULL) + continue; + + /* For each hash entry on this slot... */ + he = ht->table[i]; + while (he) { + unsigned int h; + + nextHe = he->next; + /* Get the new element index */ + h = Jim_HashKey(ht, he->key) & n.sizemask; + he->next = n.table[h]; + n.table[h] = he; + ht->used--; + /* Pass to the next element */ + he = nextHe; + } + } + assert(ht->used == 0); + Jim_Free(ht->table); + + /* Remap the new hashtable in the old */ + *ht = n; + return JIM_OK; +} + +/* Add an element to the target hash table */ +int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + int idx; + Jim_HashEntry *entry; + + /* Get the index of the new element, or -1 if + * the element already exists. */ + if ((idx = JimInsertHashEntry(ht, key)) == -1) + return JIM_ERR; + + /* Allocates the memory and stores key */ + entry = Jim_Alloc(sizeof(*entry)); + entry->next = ht->table[idx]; + ht->table[idx] = entry; + + /* Set the hash entry fields. */ + Jim_SetHashKey(ht, entry, key); + Jim_SetHashVal(ht, entry, val); + ht->used++; + return JIM_OK; +} + +/* Add an element, discarding the old if the key already exists */ +int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + Jim_HashEntry *entry; + + /* Try to add the element. If the key + * does not exists Jim_AddHashEntry will suceed. */ + if (Jim_AddHashEntry(ht, key, val) == JIM_OK) + return JIM_OK; + /* It already exists, get the entry */ + entry = Jim_FindHashEntry(ht, key); + /* Free the old value and set the new one */ + Jim_FreeEntryVal(ht, entry); + Jim_SetHashVal(ht, entry, val); + return JIM_OK; +} + +/* Search and remove an element */ +int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key) +{ + unsigned int h; + Jim_HashEntry *he, *prevHe; + + if (ht->used == 0) + return JIM_ERR; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + + prevHe = NULL; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) { + /* Unlink the element from the list */ + if (prevHe) + prevHe->next = he->next; + else + ht->table[h] = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + return JIM_OK; + } + prevHe = he; + he = he->next; + } + return JIM_ERR; /* not found */ +} + +/* Destroy an entire hash table */ +int Jim_FreeHashTable(Jim_HashTable *ht) +{ + unsigned int i; + + /* Free all the elements */ + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if ((he = ht->table[i]) == NULL) + continue; + while (he) { + nextHe = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + he = nextHe; + } + } + /* Free the table and the allocated cache structure */ + Jim_Free(ht->table); + /* Re-initialize the table */ + JimResetHashTable(ht); + return JIM_OK; /* never fails */ +} + +Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) +{ + Jim_HashEntry *he; + unsigned int h; + + if (ht->used == 0) + return NULL; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return he; + he = he->next; + } + return NULL; +} + +Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) +{ + Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); + + iter->ht = ht; + iter->index = -1; + iter->entry = NULL; + iter->nextEntry = NULL; + return iter; +} + +Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) +{ + while (1) { + if (iter->entry == NULL) { + iter->index++; + if (iter->index >= (signed)iter->ht->size) + break; + iter->entry = iter->ht->table[iter->index]; + } + else { + iter->entry = iter->nextEntry; + } + if (iter->entry) { + /* We need to save the 'next' here, the iterator user + * may delete the entry we are returning. */ + iter->nextEntry = iter->entry->next; + return iter->entry; + } + } + return NULL; +} + +/* ------------------------- private functions ------------------------------ */ + +/* Expand the hash table if needed */ +static int JimExpandHashTableIfNeeded(Jim_HashTable *ht) +{ + /* If the hash table is empty expand it to the intial size, + * if the table is "full" dobule its size. */ + if (ht->size == 0) + return Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE); + if (ht->size == ht->used) + return Jim_ExpandHashTable(ht, ht->size * 2); + return JIM_OK; +} + +/* Our hash table capability is a power of two */ +static unsigned int JimHashTableNextPower(unsigned int size) +{ + unsigned int i = JIM_HT_INITIAL_SIZE; + + if (size >= 2147483648U) + return 2147483648U; + while (1) { + if (i >= size) + return i; + i *= 2; + } +} + +/* Returns the index of a free slot that can be populated with + * an hash entry for the given 'key'. + * If the key already exists, -1 is returned. */ +static int JimInsertHashEntry(Jim_HashTable *ht, const void *key) +{ + unsigned int h; + Jim_HashEntry *he; + + /* Expand the hashtable if needed */ + if (JimExpandHashTableIfNeeded(ht) == JIM_ERR) + return -1; + /* Compute the key hash value */ + h = Jim_HashKey(ht, key) & ht->sizemask; + /* Search if this slot does not already contain the given key */ + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return -1; + he = he->next; + } + return h; +} + +/* ----------------------- StringCopy Hash Table Type ------------------------*/ + +static unsigned int JimStringCopyHTHashFunction(const void *key) +{ + return Jim_GenHashFunction(key, strlen(key)); +} + +static const void *JimStringCopyHTKeyDup(void *privdata, const void *key) +{ + int len = strlen(key); + char *copy = Jim_Alloc(len + 1); + + JIM_NOTUSED(privdata); + + memcpy(copy, key, len); + copy[len] = '\0'; + return copy; +} + +static void *JimStringKeyValCopyHTValDup(void *privdata, const void *val) +{ + int len = strlen(val); + char *copy = Jim_Alloc(len + 1); + + JIM_NOTUSED(privdata); + + memcpy(copy, val, len); + copy[len] = '\0'; + return copy; +} + +static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return strcmp(key1, key2) == 0; +} + +static void JimStringCopyHTKeyDestructor(void *privdata, const void *key) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)key); /* ATTENTION: const cast */ +} + +static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)val); /* ATTENTION: const cast */ +} + +#if 0 +static Jim_HashTableType JimStringCopyHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; +#endif + +/* This is like StringCopy but does not auto-duplicate the key. + * It's used for intepreter's shared strings. */ +static const Jim_HashTableType JimSharedStringsHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + NULL, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; + +/* This is like StringCopy but also automatically handle dynamic + * allocated C strings as values. */ +static const Jim_HashTableType JimStringKeyValCopyHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + JimStringKeyValCopyHTValDup, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimStringKeyValCopyHTValDestructor, /* val destructor */ +}; + +typedef struct AssocDataValue +{ + Jim_InterpDeleteProc *delProc; + void *data; +} AssocDataValue; + +static void JimAssocDataHashTableValueDestructor(void *privdata, void *data) +{ + AssocDataValue *assocPtr = (AssocDataValue *) data; + + if (assocPtr->delProc != NULL) + assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); + Jim_Free(data); +} + +static const Jim_HashTableType JimAssocDataHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimAssocDataHashTableValueDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Stack - This is a simple generic stack implementation. It is used for + * example in the 'expr' expression compiler. + * ---------------------------------------------------------------------------*/ +void Jim_InitStack(Jim_Stack *stack) +{ + stack->len = 0; + stack->maxlen = 0; + stack->vector = NULL; +} + +void Jim_FreeStack(Jim_Stack *stack) +{ + Jim_Free(stack->vector); +} + +int Jim_StackLen(Jim_Stack *stack) +{ + return stack->len; +} + +void Jim_StackPush(Jim_Stack *stack, void *element) +{ + int neededLen = stack->len + 1; + + if (neededLen > stack->maxlen) { + stack->maxlen = neededLen < 20 ? 20 : neededLen * 2; + stack->vector = Jim_Realloc(stack->vector, sizeof(void *) * stack->maxlen); + } + stack->vector[stack->len] = element; + stack->len++; +} + +void *Jim_StackPop(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + stack->len--; + return stack->vector[stack->len]; +} + +void *Jim_StackPeek(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + return stack->vector[stack->len - 1]; +} + +void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr)) +{ + int i; + + for (i = 0; i < stack->len; i++) + freeFunc(stack->vector[i]); +} + +/* ----------------------------------------------------------------------------- + * Parser + * ---------------------------------------------------------------------------*/ + +/* Token types */ +#define JIM_TT_NONE 0 /* No token returned */ +#define JIM_TT_STR 1 /* simple string */ +#define JIM_TT_ESC 2 /* string that needs escape chars conversion */ +#define JIM_TT_VAR 3 /* var substitution */ +#define JIM_TT_DICTSUGAR 4 /* Syntax sugar for [dict get], $foo(bar) */ +#define JIM_TT_CMD 5 /* command substitution */ +/* Note: Keep these three together for TOKEN_IS_SEP() */ +#define JIM_TT_SEP 6 /* word separator. arg is # of tokens. -ve if {*} */ +#define JIM_TT_EOL 7 /* line separator */ +#define JIM_TT_EOF 8 /* end of script */ + +#define JIM_TT_LINE 9 /* special 'start-of-line' token. arg is # of arguments to the command. -ve if {*} */ +#define JIM_TT_WORD 10 /* special 'start-of-word' token. arg is # of tokens to combine. -ve if {*} */ + +/* Additional token types needed for expressions */ +#define JIM_TT_SUBEXPR_START 11 +#define JIM_TT_SUBEXPR_END 12 +#define JIM_TT_SUBEXPR_COMMA 13 +#define JIM_TT_EXPR_INT 14 +#define JIM_TT_EXPR_DOUBLE 15 + +#define JIM_TT_EXPRSUGAR 16 /* $(expression) */ + +/* Operator token types start here */ +#define JIM_TT_EXPR_OP 20 + +#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) + +/* Parser states */ +#define JIM_PS_DEF 0 /* Default state */ +#define JIM_PS_QUOTE 1 /* Inside "" */ +#define JIM_PS_DICTSUGAR 2 /* Tokenising abc(def) into 4 separate tokens */ + +/* Parser context structure. The same context is used both to parse + * Tcl scripts and lists. */ +struct JimParserCtx +{ + const char *p; /* Pointer to the point of the program we are parsing */ + int len; /* Remaining length */ + int linenr; /* Current line number */ + const char *tstart; + const char *tend; /* Returned token is at tstart-tend in 'prg'. */ + int tline; /* Line number of the returned token */ + int tt; /* Token type */ + int eof; /* Non zero if EOF condition is true. */ + int state; /* Parser state */ + int comment; /* Non zero if the next chars may be a comment. */ + char missing; /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */ + int missingline; /* Line number starting the missing token */ +}; + +/** + * Results of missing quotes, braces, etc. from parsing. + */ +struct JimParseResult { + char missing; /* From JimParserCtx.missing */ + int line; /* From JimParserCtx.missingline */ +}; + +static int JimParseScript(struct JimParserCtx *pc); +static int JimParseSep(struct JimParserCtx *pc); +static int JimParseEol(struct JimParserCtx *pc); +static int JimParseCmd(struct JimParserCtx *pc); +static int JimParseQuote(struct JimParserCtx *pc); +static int JimParseVar(struct JimParserCtx *pc); +static int JimParseBrace(struct JimParserCtx *pc); +static int JimParseStr(struct JimParserCtx *pc); +static int JimParseComment(struct JimParserCtx *pc); +static void JimParseSubCmd(struct JimParserCtx *pc); +static int JimParseSubQuote(struct JimParserCtx *pc); +static void JimParseSubCmd(struct JimParserCtx *pc); +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); + +/* Initialize a parser context. + * 'prg' is a pointer to the program text, linenr is the line + * number of the first line contained in the program. */ +static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) +{ + pc->p = prg; + pc->len = len; + pc->tstart = NULL; + pc->tend = NULL; + pc->tline = 0; + pc->tt = JIM_TT_NONE; + pc->eof = 0; + pc->state = JIM_PS_DEF; + pc->linenr = linenr; + pc->comment = 1; + pc->missing = ' '; + pc->missingline = linenr; +} + +static int JimParseScript(struct JimParserCtx *pc) +{ + while (1) { /* the while is used to reiterate with continue if needed */ + if (!pc->len) { + pc->tstart = pc->p; + pc->tend = pc->p - 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '\\': + if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) { + return JimParseSep(pc); + } + else { + pc->comment = 0; + return JimParseStr(pc); + } + break; + case ' ': + case '\t': + case '\r': + if (pc->state == JIM_PS_DEF) + return JimParseSep(pc); + else { + pc->comment = 0; + return JimParseStr(pc); + } + break; + case '\n': + case ';': + pc->comment = 1; + if (pc->state == JIM_PS_DEF) + return JimParseEol(pc); + else + return JimParseStr(pc); + break; + case '[': + pc->comment = 0; + return JimParseCmd(pc); + break; + case '$': + pc->comment = 0; + if (JimParseVar(pc) == JIM_ERR) { + pc->tstart = pc->tend = pc->p++; + pc->len--; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + return JIM_OK; + } + else + return JIM_OK; + break; + case '#': + if (pc->comment) { + JimParseComment(pc); + continue; + } + else { + return JimParseStr(pc); + } + default: + pc->comment = 0; + return JimParseStr(pc); + break; + } + return JIM_OK; + } +} + +static int JimParseSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || + (*pc->p == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\\') { + pc->p++; + pc->len--; + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseEol(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\n' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == ';') { + if (*pc->p == '\n') + pc->linenr++; + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_EOL; + return JIM_OK; +} + +/* +** Here are the rules for parsing: +** {braced expression} +** - Count open and closing braces +** - Backslash escapes meaning of braces +** +** "quoted expression" +** - First double quote at start of word terminates the expression +** - Backslash escapes quote and bracket +** - [commands brackets] are counted/nested +** - command rules apply within [brackets], not quoting rules (i.e. quotes have their own rules) +** +** [command expression] +** - Count open and closing brackets +** - Backslash escapes quote, bracket and brace +** - [commands brackets] are counted/nested +** - "quoted expressions" are parsed according to quoting rules +** - {braced expressions} are parsed according to brace rules +** +** For everything, backslash escapes the next char, newline increments current line +*/ + +/** + * Parses a braced expression starting at pc->p. + * + * Positions the parser at the end of the braced expression, + * sets pc->tend and possibly pc->missing. + */ +static void JimParseSubBrace(struct JimParserCtx *pc) +{ + int level = 1; + + /* Skip the brace */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '{': + level++; + break; + + case '}': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '\n': + pc->linenr++; + break; + } + pc->p++; + pc->len--; + } + pc->missing = '{'; + pc->missingline = pc->tline; + pc->tend = pc->p - 1; +} + +/** + * Parses a quoted expression starting at pc->p. + * + * Positions the parser at the end of the quoted expression, + * sets pc->tend and possibly pc->missing. + * + * Returns the type of the token of the string, + * either JIM_TT_ESC (if it contains values which need to be [subst]ed) + * or JIM_TT_STR. + */ +static int JimParseSubQuote(struct JimParserCtx *pc) +{ + int tt = JIM_TT_STR; + int line = pc->tline; + + /* Skip the quote */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + tt = JIM_TT_ESC; + } + break; + + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return tt; + + case '[': + JimParseSubCmd(pc); + tt = JIM_TT_ESC; + continue; + + case '\n': + pc->linenr++; + break; + + case '$': + tt = JIM_TT_ESC; + break; + } + pc->p++; + pc->len--; + } + pc->missing = '"'; + pc->missingline = line; + pc->tend = pc->p - 1; + return tt; +} + +/** + * Parses a [command] expression starting at pc->p. + * + * Positions the parser at the end of the command expression, + * sets pc->tend and possibly pc->missing. + */ +static void JimParseSubCmd(struct JimParserCtx *pc) +{ + int level = 1; + int startofword = 1; + int line = pc->tline; + + /* Skip the bracket */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '[': + level++; + break; + + case ']': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '"': + if (startofword) { + JimParseSubQuote(pc); + continue; + } + break; + + case '{': + JimParseSubBrace(pc); + startofword = 0; + continue; + + case '\n': + pc->linenr++; + break; + } + startofword = isspace(UCHAR(*pc->p)); + pc->p++; + pc->len--; + } + pc->missing = '['; + pc->missingline = line; + pc->tend = pc->p - 1; +} + +static int JimParseBrace(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + JimParseSubBrace(pc); + return JIM_OK; +} + +static int JimParseCmd(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_CMD; + JimParseSubCmd(pc); + return JIM_OK; +} + +static int JimParseQuote(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JimParseSubQuote(pc); + return JIM_OK; +} + +static int JimParseVar(struct JimParserCtx *pc) +{ + /* skip the $ */ + pc->p++; + pc->len--; + +#ifdef EXPRSUGAR_BRACKET + if (*pc->p == '[') { + /* Parse $[...] expr shorthand syntax */ + JimParseCmd(pc); + pc->tt = JIM_TT_EXPRSUGAR; + return JIM_OK; + } +#endif + + pc->tstart = pc->p; + pc->tt = JIM_TT_VAR; + pc->tline = pc->linenr; + + if (*pc->p == '{') { + pc->tstart = ++pc->p; + pc->len--; + + while (pc->len && *pc->p != '}') { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + if (pc->len) { + pc->p++; + pc->len--; + } + } + else { + while (1) { + /* Skip double colon, but not single colon! */ + if (pc->p[0] == ':' && pc->p[1] == ':') { + pc->p += 2; + pc->len -= 2; + continue; + } + if (isalnum(UCHAR(*pc->p)) || *pc->p == '_') { + pc->p++; + pc->len--; + continue; + } + break; + } + /* Parse [dict get] syntax sugar. */ + if (*pc->p == '(') { + int count = 1; + const char *paren = NULL; + + pc->tt = JIM_TT_DICTSUGAR; + + while (count && pc->len) { + pc->p++; + pc->len--; + if (*pc->p == '\\' && pc->len >= 1) { + pc->p++; + pc->len--; + } + else if (*pc->p == '(') { + count++; + } + else if (*pc->p == ')') { + paren = pc->p; + count--; + } + } + if (count == 0) { + pc->p++; + pc->len--; + } + else if (paren) { + /* Did not find a matching paren. Back up */ + paren++; + pc->len += (pc->p - paren); + pc->p = paren; + } +#ifndef EXPRSUGAR_BRACKET + if (*pc->tstart == '(') { + pc->tt = JIM_TT_EXPRSUGAR; + } +#endif + } + pc->tend = pc->p - 1; + } + /* Check if we parsed just the '$' character. + * That's not a variable so an error is returned + * to tell the state machine to consider this '$' just + * a string. */ + if (pc->tstart == pc->p) { + pc->p--; + pc->len++; + return JIM_ERR; + } + return JIM_OK; +} + +static int JimParseStr(struct JimParserCtx *pc) +{ + int newword = (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || + pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR); + if (newword && *pc->p == '{') { + return JimParseBrace(pc); + } + else if (newword && *pc->p == '"') { + pc->state = JIM_PS_QUOTE; + pc->p++; + pc->len--; + /* In case the end quote is missing */ + pc->missingline = pc->tline; + } + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (1) { + if (pc->len == 0) { + if (pc->state == JIM_PS_QUOTE) { + pc->missing = '"'; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + switch (*pc->p) { + case '\\': + if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + if (pc->len >= 2) { + if (*(pc->p + 1) == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + break; + case '(': + /* If the following token is not '$' just keep going */ + if (pc->len > 1 && pc->p[1] != '$') { + break; + } + case ')': + /* Only need a separate ')' token if the previous was a var */ + if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { + if (pc->p == pc->tstart) { + /* At the start of the token, so just return this char */ + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + break; + + case '$': + case '[': + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + case ' ': + case '\t': + case '\n': + case '\r': + case ';': + if (pc->state == JIM_PS_DEF) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + else if (*pc->p == '\n') { + pc->linenr++; + } + break; + case '"': + if (pc->state == JIM_PS_QUOTE) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + pc->p++; + pc->len--; + pc->state = JIM_PS_DEF; + return JIM_OK; + } + break; + } + pc->p++; + pc->len--; + } + return JIM_OK; /* unreached */ +} + +static int JimParseComment(struct JimParserCtx *pc) +{ + while (*pc->p) { + if (*pc->p == '\n') { + pc->linenr++; + if (*(pc->p - 1) != '\\') { + pc->p++; + pc->len--; + return JIM_OK; + } + } + pc->p++; + pc->len--; + } + return JIM_OK; +} + +/* xdigitval and odigitval are helper functions for JimEscape() */ +static int xdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int odigitval(int c) +{ + if (c >= '0' && c <= '7') + return c - '0'; + return -1; +} + +/* Perform Tcl escape substitution of 's', storing the result + * string into 'dest'. The escaped string is guaranteed to + * be the same length or shorted than the source string. + * Slen is the length of the string at 's', if it's -1 the string + * length will be calculated by the function. + * + * The function returns the length of the resulting string. */ +static int JimEscape(char *dest, const char *s, int slen) +{ + char *p = dest; + int i, len; + + if (slen == -1) + slen = strlen(s); + + for (i = 0; i < slen; i++) { + switch (s[i]) { + case '\\': + switch (s[i + 1]) { + case 'a': + *p++ = 0x7; + i++; + break; + case 'b': + *p++ = 0x8; + i++; + break; + case 'f': + *p++ = 0xc; + i++; + break; + case 'n': + *p++ = 0xa; + i++; + break; + case 'r': + *p++ = 0xd; + i++; + break; + case 't': + *p++ = 0x9; + i++; + break; + case 'u': + case 'x': + /* A unicode or hex sequence. + * \u Expect 1-4 hex chars and convert to utf-8. + * \x Expect 1-2 hex chars and convert to hex. + * An invalid sequence means simply the escaped char. + */ + { + int val = 0; + int k; + + i++; + + for (k = 0; k < (s[i] == 'u' ? 4 : 2); k++) { + int c = xdigitval(s[i + k + 1]); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + if (k) { + /* Got a valid sequence, so convert */ + if (s[i] == 'u') { + p += utf8_fromunicode(p, val); + } + else { + *p++ = val; + } + i += k; + break; + } + /* Not a valid codepoint, just an escaped char */ + *p++ = s[i]; + } + break; + case 'v': + *p++ = 0xb; + i++; + break; + case '\0': + *p++ = '\\'; + i++; + break; + case '\n': + /* Replace all spaces and tabs after backslash newline with a single space*/ + *p++ = ' '; + do { + i++; + } while (s[i + 1] == ' ' || s[i + 1] == '\t'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + /* octal escape */ + { + int val = 0; + int c = odigitval(s[i + 1]); + + val = c; + c = odigitval(s[i + 2]); + if (c == -1) { + *p++ = val; + i++; + break; + } + val = (val * 8) + c; + c = odigitval(s[i + 3]); + if (c == -1) { + *p++ = val; + i += 2; + break; + } + val = (val * 8) + c; + *p++ = val; + i += 3; + } + break; + default: + *p++ = s[i + 1]; + i++; + break; + } + break; + default: + *p++ = s[i]; + break; + } + } + len = p - dest; + *p = '\0'; + return len; +} + +/* Returns a dynamically allocated copy of the current token in the + * parser context. The function performs conversion of escapes if + * the token is of type JIM_TT_ESC. + * + * Note that after the conversion, tokens that are grouped with + * braces in the source code, are always recognizable from the + * identical string obtained in a different way from the type. + * + * For example the string: + * + * {*}$a + * + * will return as first token "*", of type JIM_TT_STR + * + * While the string: + * + * *$a + * + * will return as first token "*", of type JIM_TT_ESC + */ +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc) +{ + const char *start, *end; + char *token; + int len; + + start = pc->tstart; + end = pc->tend; + if (start > end) { + len = 0; + token = Jim_Alloc(1); + token[0] = '\0'; + } + else { + len = (end - start) + 1; + token = Jim_Alloc(len + 1); + if (pc->tt != JIM_TT_ESC) { + /* No escape conversion needed? Just copy it. */ + memcpy(token, start, len); + token[len] = '\0'; + } + else { + /* Else convert the escape chars. */ + len = JimEscape(token, start, len); + } + } + + return Jim_NewStringObjNoAlloc(interp, token, len); +} + +/* Parses the given string to determine if it represents a complete script. + * + * This is useful for interactive shells implementation, for [info complete]. + * + * If 'stateCharPtr' != NULL, the function stores ' ' on complete script, + * '{' on scripts incomplete missing one or more '}' to be balanced. + * '[' on scripts incomplete missing one or more ']' to be balanced. + * '"' on scripts incomplete missing a '"' char. + * + * If the script is complete, 1 is returned, otherwise 0. + */ +int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr) +{ + struct JimParserCtx parser; + + JimParserInit(&parser, s, len, 1); + while (!parser.eof) { + JimParseScript(&parser); + } + if (stateCharPtr) { + *stateCharPtr = parser.missing; + } + return parser.missing == ' '; +} + +/* ----------------------------------------------------------------------------- + * Tcl Lists parsing + * ---------------------------------------------------------------------------*/ +static int JimParseListSep(struct JimParserCtx *pc); +static int JimParseListStr(struct JimParserCtx *pc); +static int JimParseListQuote(struct JimParserCtx *pc); + +static int JimParseList(struct JimParserCtx *pc) +{ + switch (*pc->p) { + case ' ': + case '\n': + case '\t': + case '\r': + return JimParseListSep(pc); + + case '"': + return JimParseListQuote(pc); + + case '{': + return JimParseBrace(pc); + + default: + if (pc->len) { + return JimParseListStr(pc); + } + break; + } + + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; +} + +static int JimParseListSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == '\n') { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseListQuote(struct JimParserCtx *pc) +{ + pc->p++; + pc->len--; + + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + switch (*pc->p) { + case '\\': + pc->tt = JIM_TT_ESC; + if (--pc->len == 0) { + /* Trailing backslash */ + pc->tend = pc->p; + return JIM_OK; + } + pc->p++; + break; + case '\n': + pc->linenr++; + break; + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return JIM_OK; + } + pc->p++; + pc->len--; + } + + pc->tend = pc->p - 1; + return JIM_OK; +} + +static int JimParseListStr(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + switch (*pc->p) { + case '\\': + if (--pc->len == 0) { + /* Trailing backslash */ + pc->tend = pc->p; + return JIM_OK; + } + pc->tt = JIM_TT_ESC; + pc->p++; + break; + case ' ': + case '\t': + case '\n': + case '\r': + pc->tend = pc->p - 1; + return JIM_OK; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Jim_Obj related functions + * ---------------------------------------------------------------------------*/ + +/* Return a new initialized object. */ +Jim_Obj *Jim_NewObj(Jim_Interp *interp) +{ + Jim_Obj *objPtr; + + /* -- Check if there are objects in the free list -- */ + if (interp->freeList != NULL) { + /* -- Unlink the object from the free list -- */ + objPtr = interp->freeList; + interp->freeList = objPtr->nextObjPtr; + } + else { + /* -- No ready to use objects: allocate a new one -- */ + objPtr = Jim_Alloc(sizeof(*objPtr)); + } + + /* Object is returned with refCount of 0. Every + * kind of GC implemented should take care to don't try + * to scan objects with refCount == 0. */ + objPtr->refCount = 0; + /* All the other fields are left not initialized to save time. + * The caller will probably want to set them to the right + * value anyway. */ + + /* -- Put the object into the live list -- */ + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->liveList; + if (interp->liveList) + interp->liveList->prevObjPtr = objPtr; + interp->liveList = objPtr; + + return objPtr; +} + +/* Free an object. Actually objects are never freed, but + * just moved to the free objects list, where they will be + * reused by Jim_NewObj(). */ +void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + /* Check if the object was already freed, panic. */ + JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, + objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>")); + + /* Free the internal representation */ + Jim_FreeIntRep(interp, objPtr); + /* Free the string representation */ + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + /* Unlink the object from the live objects list */ + if (objPtr->prevObjPtr) + objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; + if (objPtr->nextObjPtr) + objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; + if (interp->liveList == objPtr) + interp->liveList = objPtr->nextObjPtr; + /* Link the object into the free objects list */ + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->freeList; + if (interp->freeList) + interp->freeList->prevObjPtr = objPtr; + interp->freeList = objPtr; + objPtr->refCount = -1; +} + +/* Invalidate the string representation of an object. */ +void Jim_InvalidateStringRep(Jim_Obj *objPtr) +{ + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + objPtr->bytes = NULL; +} + +#define Jim_SetStringRep(o, b, l) \ + do { (o)->bytes = b; (o)->length = l; } while (0) + +/* Set the initial string representation for an object. + * Does not try to free an old one. */ +void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length) +{ + if (length == 0) { + objPtr->bytes = JimEmptyStringRep; + objPtr->length = 0; + } + else { + objPtr->bytes = Jim_Alloc(length + 1); + objPtr->length = length; + memcpy(objPtr->bytes, bytes, length); + objPtr->bytes[length] = '\0'; + } +} + +/* Duplicate an object. The returned object has refcount = 0. */ +Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *dupPtr; + + dupPtr = Jim_NewObj(interp); + if (objPtr->bytes == NULL) { + /* Object does not have a valid string representation. */ + dupPtr->bytes = NULL; + } + else { + Jim_InitStringRep(dupPtr, objPtr->bytes, objPtr->length); + } + + /* By default, the new object has the same type as the old object */ + dupPtr->typePtr = objPtr->typePtr; + if (objPtr->typePtr != NULL) { + if (objPtr->typePtr->dupIntRepProc == NULL) { + dupPtr->internalRep = objPtr->internalRep; + } + else { + /* The dup proc may set a different type, e.g. NULL */ + objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); + } + } + return dupPtr; +} + +/* Return the string representation for objPtr. If the object + * string representation is invalid, calls the method to create + * a new one starting from the internal representation of the object. */ +const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) +{ + if (objPtr->bytes == NULL) { + /* Invalid string repr. Generate it. */ + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + if (lenPtr) + *lenPtr = objPtr->length; + return objPtr->bytes; +} + +/* Just returns the length of the object's string rep */ +int Jim_Length(Jim_Obj *objPtr) +{ + int len; + + Jim_GetString(objPtr, &len); + return len; +} + +static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType dictSubstObjType = { + "dict-substitution", + FreeDictSubstInternalRep, + DupDictSubstInternalRep, + NULL, + JIM_TYPE_NONE, +}; + +static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, (Jim_Obj *)objPtr->internalRep.twoPtrValue.ptr2); +} + +static const Jim_ObjType interpolatedObjType = { + "interpolated", + FreeInterpolatedInternalRep, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +/* ----------------------------------------------------------------------------- + * String Object + * ---------------------------------------------------------------------------*/ +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType stringObjType = { + "string", + NULL, + DupStringInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + /* This is a bit subtle: the only caller of this function + * should be Jim_DuplicateObj(), that will copy the + * string representaion. After the copy, the duplicated + * object will not have more room in teh buffer than + * srcPtr->length bytes. So we just set it to length. */ + dupPtr->internalRep.strValue.maxLength = srcPtr->length; + + dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; +} + +static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + /* Get a fresh string representation. */ + (void)Jim_String(objPtr); + /* Free any other internal representation. */ + Jim_FreeIntRep(interp, objPtr); + /* Set it as string, i.e. just set the maxLength field. */ + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = objPtr->length; + /* Don't know the utf-8 length yet */ + objPtr->internalRep.strValue.charLength = -1; + return JIM_OK; +} + +/** + * Returns the length of the object string in chars, not bytes. + * + * These may be different for a utf-8 string. + */ +int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr) +{ +#ifdef JIM_UTF8 + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + + if (objPtr->internalRep.strValue.charLength < 0) { + objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length); + } + return objPtr->internalRep.strValue.charLength; +#else + return Jim_Length(objPtr); +#endif +} + +/* len is in bytes -- see also Jim_NewStringObjUtf8() */ +Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + /* Need to find out how many bytes the string requires */ + if (len == -1) + len = strlen(s); + /* Alloc/Set the string rep. */ + if (len == 0) { + objPtr->bytes = JimEmptyStringRep; + objPtr->length = 0; + } + else { + objPtr->bytes = Jim_Alloc(len + 1); + objPtr->length = len; + memcpy(objPtr->bytes, s, len); + objPtr->bytes[len] = '\0'; + } + + /* No typePtr field for the vanilla string object. */ + objPtr->typePtr = NULL; + return objPtr; +} + +/* charlen is in characters -- see also Jim_NewStringObj() */ +Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) +{ +#ifdef JIM_UTF8 + /* Need to find out how many bytes the string requires */ + int bytelen = utf8_index(s, charlen); + + Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); + + /* Remember the utf8 length, so set the type */ + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = bytelen; + objPtr->internalRep.strValue.charLength = charlen; + + return objPtr; +#else + return Jim_NewStringObj(interp, s, charlen); +#endif +} + +/* This version does not try to duplicate the 's' pointer, but + * use it directly. */ +Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + if (len == -1) + len = strlen(s); + Jim_SetStringRep(objPtr, s, len); + objPtr->typePtr = NULL; + return objPtr; +} + +/* Low-level string append. Use it only against objects + * of type "string". */ +static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) +{ + int needlen; + + if (len == -1) + len = strlen(str); + needlen = objPtr->length + len; + if (objPtr->internalRep.strValue.maxLength < needlen || + objPtr->internalRep.strValue.maxLength == 0) { + needlen *= 2; + /* Inefficient to malloc() for less than 8 bytes */ + if (needlen < 7) { + needlen = 7; + } + if (objPtr->bytes == JimEmptyStringRep) { + objPtr->bytes = Jim_Alloc(needlen + 1); + } + else { + objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1); + } + objPtr->internalRep.strValue.maxLength = needlen; + } + memcpy(objPtr->bytes + objPtr->length, str, len); + objPtr->bytes[objPtr->length + len] = '\0'; + if (objPtr->internalRep.strValue.charLength >= 0) { + /* Update the utf-8 char length */ + objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); + } + objPtr->length += len; +} + +/* Higher level API to append strings to objects. */ +void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) +{ + JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + StringAppendString(objPtr, str, len); +} + +void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) +{ + int len; + const char *str; + + str = Jim_GetString(appendObjPtr, &len); + Jim_AppendString(interp, objPtr, str, len); +} + +void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) +{ + va_list ap; + + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + va_start(ap, objPtr); + while (1) { + char *s = va_arg(ap, char *); + + if (s == NULL) + break; + Jim_AppendString(interp, objPtr, s, -1); + } + va_end(ap); +} + +int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) +{ + const char *aStr, *bStr; + int aLen, bLen; + + if (aObjPtr == bObjPtr) + return 1; + aStr = Jim_GetString(aObjPtr, &aLen); + bStr = Jim_GetString(bObjPtr, &bLen); + if (aLen != bLen) + return 0; + return JimStringCompare(aStr, aLen, bStr, bLen) == 0; +} + +int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) +{ + return JimStringMatch(interp, patternObjPtr, Jim_String(objPtr), nocase); +} + +int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) +{ + const char *s1, *s2; + int l1, l2; + + s1 = Jim_GetString(firstObjPtr, &l1); + s2 = Jim_GetString(secondObjPtr, &l2); + + if (nocase) { + return JimStringCompareNoCase(s1, s2, -1); + } + return JimStringCompare(s1, l1, s2, l2); +} + +/* Convert a range, as returned by Jim_GetRange(), into + * an absolute index into an object of the specified length. + * This function may return negative values, or values + * bigger or equal to the length of the list if the index + * is out of range. */ +static int JimRelToAbsIndex(int len, int idx) +{ + if (idx < 0) + return len + idx; + return idx; +} + +/* Convert a pair of index as normalize by JimRelToAbsIndex(), + * into a range stored in *firstPtr, *lastPtr, *rangeLenPtr, suitable + * for implementation of commands like [string range] and [lrange]. + * + * The resulting range is guaranteed to address valid elements of + * the structure. */ +static void JimRelToAbsRange(int len, int first, int last, + int *firstPtr, int *lastPtr, int *rangeLenPtr) +{ + int rangeLen; + + if (first > last) { + rangeLen = 0; + } + else { + rangeLen = last - first + 1; + if (rangeLen) { + if (first < 0) { + rangeLen += first; + first = 0; + } + if (last >= len) { + rangeLen -= (last - (len - 1)); + last = len - 1; + } + } + } + if (rangeLen < 0) + rangeLen = 0; + + *firstPtr = first; + *lastPtr = last; + *rangeLenPtr = rangeLen; +} + +Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ + int first, last; + const char *str; + int rangeLen; + int bytelen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + str = Jim_GetString(strObjPtr, &bytelen); + first = JimRelToAbsIndex(bytelen, first); + last = JimRelToAbsIndex(bytelen, last); + JimRelToAbsRange(bytelen, first, last, &first, &last, &rangeLen); + if (first == 0 && rangeLen == bytelen) { + return strObjPtr; + } + return Jim_NewStringObj(interp, str + first, rangeLen); +} + +Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ +#ifdef JIM_UTF8 + int first, last; + const char *str; + int len, rangeLen; + int bytelen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + str = Jim_GetString(strObjPtr, &bytelen); + len = Jim_Utf8Length(interp, strObjPtr); + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + if (first == 0 && rangeLen == len) { + return strObjPtr; + } + if (len == bytelen) { + /* ASCII optimisation */ + return Jim_NewStringObj(interp, str + first, rangeLen); + } + return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); +#else + return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); +#endif +} + +static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf, *p; + int len; + const char *str; + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + str = Jim_GetString(strObjPtr, &len); + + buf = p = Jim_Alloc(len + 1); + while (*str) { + int c; + str += utf8_tounicode(str, &c); + p += utf8_fromunicode(p, utf8_lower(c)); + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buf, len); +} + +static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf, *p; + int len; + const char *str; + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + str = Jim_GetString(strObjPtr, &len); + + buf = p = Jim_Alloc(len + 1); + while (*str) { + int c; + str += utf8_tounicode(str, &c); + p += utf8_fromunicode(p, utf8_upper(c)); + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buf, len); +} + +/* Similar to memchr() except searches a UTF-8 string 'str' of byte length 'len' + * for unicode character 'c'. + * Returns the position if found or NULL if not + */ +static const char *utf8_memchr(const char *str, int len, int c) +{ +#ifdef JIM_UTF8 + while (len) { + int sc; + int n = utf8_tounicode(str, &sc); + if (sc == c) { + return str; + } + str += n; + len -= n; + } + return NULL; +#else + return memchr(str, c, len); +#endif +} + +/** + * Searches for the first non-trim char in string (str, len) + * + * If none is found, returns just past the last char. + * + * Lengths are in bytes. + */ +static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen) +{ + while (len) { + int c; + int n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + /* Not a trim char, so stop */ + break; + } + str += n; + len -= n; + } + return str; +} + +/** + * Searches backwards for a non-trim char in string (str, len). + * + * Returns a pointer to just after the non-trim char, or NULL if not found. + * + * Lengths are in bytes. + */ +static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen) +{ + str += len; + + while (len) { + int c; + int n = utf8_prev_len(str, len); + + len -= n; + str -= n; + + n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + return str + n; + } + } + + return NULL; +} + +static const char default_trim_chars[] = " \t\n\r"; +/* sizeof() here includes the null byte */ +static int default_trim_chars_len = sizeof(default_trim_chars); + +static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *str = Jim_GetString(strObjPtr, &len); + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *newstr; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + newstr = JimFindTrimLeft(str, len, trimchars, trimcharslen); + if (newstr == str) { + return strObjPtr; + } + + return Jim_NewStringObj(interp, newstr, len - (newstr - str)); +} + +static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *nontrim; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + len = Jim_Length(strObjPtr); + nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); + + if (nontrim == NULL) { + /* All trim, so return a zero-length string */ + return Jim_NewEmptyStringObj(interp); + } + if (nontrim == strObjPtr->bytes + len) { + return strObjPtr; + } + + if (Jim_IsShared(strObjPtr)) { + strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); + } + else { + /* Can modify this string in place */ + strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; + strObjPtr->length = (nontrim - strObjPtr->bytes); + } + + return strObjPtr; +} + +static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + /* First trim left. */ + Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); + + /* Now trim right */ + strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); + + if (objPtr != strObjPtr) { + /* Note that we don't want this object to be leaked */ + Jim_IncrRefCount(objPtr); + Jim_DecrRefCount(interp, objPtr); + } + + return strObjPtr; +} + + +static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) +{ + static const char * const strclassnames[] = { + "integer", "alpha", "alnum", "ascii", "digit", + "double", "lower", "upper", "space", "xdigit", + "control", "print", "graph", "punct", + NULL + }; + enum { + STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, + STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, + STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT + }; + int strclass; + int len; + int i; + const char *str; + int (*isclassfunc)(int c) = NULL; + + if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + + str = Jim_GetString(strObjPtr, &len); + if (len == 0) { + Jim_SetResultInt(interp, !strict); + return JIM_OK; + } + + switch (strclass) { + case STR_IS_INTEGER: + { + jim_wide w; + Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); + return JIM_OK; + } + + case STR_IS_DOUBLE: + { + double d; + Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); + return JIM_OK; + } + + case STR_IS_ALPHA: isclassfunc = isalpha; break; + case STR_IS_ALNUM: isclassfunc = isalnum; break; + case STR_IS_ASCII: isclassfunc = isascii; break; + case STR_IS_DIGIT: isclassfunc = isdigit; break; + case STR_IS_LOWER: isclassfunc = islower; break; + case STR_IS_UPPER: isclassfunc = isupper; break; + case STR_IS_SPACE: isclassfunc = isspace; break; + case STR_IS_XDIGIT: isclassfunc = isxdigit; break; + case STR_IS_CONTROL: isclassfunc = iscntrl; break; + case STR_IS_PRINT: isclassfunc = isprint; break; + case STR_IS_GRAPH: isclassfunc = isgraph; break; + case STR_IS_PUNCT: isclassfunc = ispunct; break; + default: + return JIM_ERR; + } + + for (i = 0; i < len; i++) { + if (!isclassfunc(str[i])) { + Jim_SetResultInt(interp, 0); + return JIM_OK; + } + } + Jim_SetResultInt(interp, 1); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Compared String Object + * ---------------------------------------------------------------------------*/ + +/* This is strange object that allows to compare a C literal string + * with a Jim object in very short time if the same comparison is done + * multiple times. For example every time the [if] command is executed, + * Jim has to check if a given argument is "else". This comparions if + * the code has no errors are true most of the times, so we can cache + * inside the object the pointer of the string of the last matching + * comparison. Because most C compilers perform literal sharing, + * so that: char *x = "foo", char *y = "foo", will lead to x == y, + * this works pretty well even if comparisons are at different places + * inside the C code. */ + +static const Jim_ObjType comparedStringObjType = { + "compared-string", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* The only way this object is exposed to the API is via the following + * function. Returns true if the string and the object string repr. + * are the same, otherwise zero is returned. + * + * Note: this isn't binary safe, but it hardly needs to be.*/ +int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) +{ + if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) + return 1; + else { + const char *objStr = Jim_String(objPtr); + + if (strcmp(str, objStr) != 0) + return 0; + if (objPtr->typePtr != &comparedStringObjType) { + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &comparedStringObjType; + } + objPtr->internalRep.ptr = (char *)str; /*ATTENTION: const cast */ + return 1; + } +} + +static int qsortCompareStringPointers(const void *a, const void *b) +{ + char *const *sa = (char *const *)a; + char *const *sb = (char *const *)b; + + return strcmp(*sa, *sb); +} + + +/* ----------------------------------------------------------------------------- + * Source Object + * + * This object is just a string from the language point of view, but + * in the internal representation it contains the filename and line number + * where this given token was read. This information is used by + * Jim_EvalObj() if the object passed happens to be of type "source". + * + * This allows to propagate the information about line numbers and file + * names and give error messages with absolute line numbers. + * + * Note that this object uses shared strings for filenames, and the + * pointer to the filename together with the line number is taken into + * the space for the "inline" internal representation of the Jim_Object, + * so there is almost memory zero-overhead. + * + * Also the object will be converted to something else if the given + * token it represents in the source file is not something to be + * evaluated (not a script), and will be specialized in some other way, + * so the time overhead is also null. + * ---------------------------------------------------------------------------*/ + +static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType sourceObjType = { + "source", + FreeSourceInternalRep, + DupSourceInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj); +} + +void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + dupPtr->internalRep = srcPtr->internalRep; + Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); +} + +static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *fileNameObj, int lineNumber) +{ + JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); + JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL")); + Jim_IncrRefCount(fileNameObj); + objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; + objPtr->internalRep.sourceValue.lineNumber = lineNumber; + objPtr->typePtr = &sourceObjType; +} + +/* ----------------------------------------------------------------------------- + * Script Object + * ---------------------------------------------------------------------------*/ + +static const Jim_ObjType scriptLineObjType = { + "scriptline", + NULL, + NULL, + NULL, + 0, +}; + +static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) +{ + Jim_Obj *objPtr; + +#ifdef DEBUG_SHOW_SCRIPT + char buf[100]; + snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc); + objPtr = Jim_NewStringObj(interp, buf, -1); +#else + objPtr = Jim_NewEmptyStringObj(interp); +#endif + objPtr->typePtr = &scriptLineObjType; + objPtr->internalRep.scriptLineValue.argc = argc; + objPtr->internalRep.scriptLineValue.line = line; + + return objPtr; +} + +#define JIM_CMDSTRUCT_EXPAND -1 + +static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result); + +static const Jim_ObjType scriptObjType = { + "script", + FreeScriptInternalRep, + DupScriptInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* The ScriptToken structure represents every token into a scriptObj. + * Every token contains an associated Jim_Obj that can be specialized + * by commands operating on it. */ +typedef struct ScriptToken +{ + int type; + Jim_Obj *objPtr; +} ScriptToken; + +/* This is the script object internal representation. An array of + * ScriptToken structures, including a pre-computed representation of the + * command length and arguments. + * + * For example the script: + * + * puts hello + * set $i $x$y [foo]BAR + * + * will produce a ScriptObj with the following Tokens: + * + * LIN 2 + * ESC puts + * ESC hello + * LIN 4 + * ESC set + * VAR i + * WRD 2 + * VAR x + * VAR y + * WRD 2 + * CMD foo + * ESC BAR + * + * "puts hello" has two args (LIN 2), composed of single tokens. + * (Note that the WRD token is omitted for the common case of a single token.) + * + * "set $i $x$y [foo]BAR" has four (LIN 4) args, the first word + * has 1 token (ESC SET), and the last has two tokens (WRD 2 CMD foo ESC BAR) + * + * The precomputation of the command structure makes Jim_Eval() faster, + * and simpler because there aren't dynamic lengths / allocations. + * + * -- {expand}/{*} handling -- + * + * Expand is handled in a special way. + * + * If a "word" begins with {*}, the word token count is -ve. + * + * For example the command: + * + * list {*}{a b} + * + * Will produce the following cmdstruct array: + * + * LIN 2 + * ESC list + * WRD -1 + * STR a b + * + * Note that the 'LIN' token also contains the source information for the + * first word of the line for error reporting purposes + * + * -- the substFlags field of the structure -- + * + * The scriptObj structure is used to represent both "script" objects + * and "subst" objects. In the second case, the there are no LIN and WRD + * tokens. Instead SEP and EOL tokens are added as-is. + * In addition, the field 'substFlags' is used to represent the flags used to turn + * the string into the internal representation used to perform the + * substitution. If this flags are not what the application requires + * the scriptObj is created again. For example the script: + * + * subst -nocommands $string + * subst -novariables $string + * + * Will recreate the internal representation of the $string object + * two times. + */ +typedef struct ScriptObj +{ + int len; /* Length as number of tokens. */ + ScriptToken *token; /* Tokens array. */ + int substFlags; /* flags used for the compilation of "subst" objects */ + int inUse; /* Used to share a ScriptObj. Currently + only used by Jim_EvalObj() as protection against + shimmering of the currently evaluated object. */ + Jim_Obj *fileNameObj; + int line; /* Line number of the first line */ +} ScriptObj; + +void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + struct ScriptObj *script = (void *)objPtr->internalRep.ptr; + + script->inUse--; + if (script->inUse != 0) + return; + for (i = 0; i < script->len; i++) { + Jim_DecrRefCount(interp, script->token[i].objPtr); + } + Jim_Free(script->token); + Jim_DecrRefCount(interp, script->fileNameObj); + Jim_Free(script); +} + +void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + /* Just returns an simple string. */ + dupPtr->typePtr = NULL; +} + +/* A simple parser token. + * All the simple tokens for the script point into the same script string rep. + */ +typedef struct +{ + const char *token; /* Pointer to the start of the token */ + int len; /* Length of this token */ + int type; /* Token type */ + int line; /* Line number */ +} ParseToken; + +/* A list of parsed tokens representing a script. + * Tokens are added to this list as the script is parsed. + * It grows as needed. + */ +typedef struct +{ + /* Start with a statically allocated list of tokens which will be expanded with realloc if needed */ + ParseToken *list; /* Array of tokens */ + int size; /* Current size of the list */ + int count; /* Number of entries used */ + ParseToken static_list[20]; /* Small initial token space to avoid allocation */ +} ParseTokenList; + +static void ScriptTokenListInit(ParseTokenList *tokenlist) +{ + tokenlist->list = tokenlist->static_list; + tokenlist->size = sizeof(tokenlist->static_list) / sizeof(ParseToken); + tokenlist->count = 0; +} + +static void ScriptTokenListFree(ParseTokenList *tokenlist) +{ + if (tokenlist->list != tokenlist->static_list) { + Jim_Free(tokenlist->list); + } +} + +/** + * Adds the new token to the tokenlist. + * The token has the given length, type and line number. + * The token list is resized as necessary. + */ +static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type, + int line) +{ + ParseToken *t; + + if (tokenlist->count == tokenlist->size) { + /* Resize the list */ + tokenlist->size *= 2; + if (tokenlist->list != tokenlist->static_list) { + tokenlist->list = + Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); + } + else { + /* The list needs to become allocated */ + tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); + memcpy(tokenlist->list, tokenlist->static_list, + tokenlist->count * sizeof(*tokenlist->list)); + } + } + t = &tokenlist->list[tokenlist->count++]; + t->token = token; + t->len = len; + t->type = type; + t->line = line; +} + +/* Counts the number of adjoining non-separator. + * + * Returns -ve if the first token is the expansion + * operator (in which case the count doesn't include + * that token). + */ +static int JimCountWordTokens(ParseToken *t) +{ + int expand = 1; + int count = 0; + + /* Is the first word {*} or {expand}? */ + if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { + if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { + /* Create an expand token */ + expand = -1; + t++; + } + } + + /* Now count non-separator words */ + while (!TOKEN_IS_SEP(t->type)) { + t++; + count++; + } + + return count * expand; +} + +/** + * Create a script/subst object from the given token. + */ +static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) +{ + Jim_Obj *objPtr; + + if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { + /* Convert the backlash escapes . */ + int len = t->len; + char *str = Jim_Alloc(len + 1); + len = JimEscape(str, t->token, len); + objPtr = Jim_NewStringObjNoAlloc(interp, str, len); + } + else { + /* REVIST: Strictly, JIM_TT_STR should replace <backslash><newline><whitespace> + * with a single space. This is currently not done. + */ + objPtr = Jim_NewStringObj(interp, t->token, t->len); + } + return objPtr; +} + +/** + * Takes a tokenlist and creates the allocated list of script tokens + * in script->token, of length script->len. + * + * Unnecessary tokens are discarded, and LINE and WORD tokens are inserted + * as required. + * + * Also sets script->line to the line number of the first token + */ +static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + /* Number of tokens so far for the current command */ + int lineargs = 0; + /* This is the first token for the current command */ + ScriptToken *linefirst; + int count; + int linenr; + +#ifdef DEBUG_SHOW_SCRIPT_TOKENS + printf("==== Tokens ====\n"); + for (i = 0; i < tokenlist->count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), + tokenlist->list[i].len, tokenlist->list[i].token); + } +#endif + + /* May need up to one extra script token for each EOL in the worst case */ + count = tokenlist->count; + for (i = 0; i < tokenlist->count; i++) { + if (tokenlist->list[i].type == JIM_TT_EOL) { + count++; + } + } + linenr = script->line = tokenlist->list[0].line; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); + + /* This is the first token for the current command */ + linefirst = token++; + + for (i = 0; i < tokenlist->count; ) { + /* Look ahead to find out how many tokens make up the next word */ + int wordtokens; + + /* Skip any leading separators */ + while (tokenlist->list[i].type == JIM_TT_SEP) { + i++; + } + + wordtokens = JimCountWordTokens(tokenlist->list + i); + + if (wordtokens == 0) { + /* None, so at end of line */ + if (lineargs) { + linefirst->type = JIM_TT_LINE; + linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); + Jim_IncrRefCount(linefirst->objPtr); + + /* Reset for new line */ + lineargs = 0; + linefirst = token++; + } + i++; + continue; + } + else if (wordtokens != 1) { + /* More than 1, or {expand}, so insert a WORD token */ + token->type = JIM_TT_WORD; + token->objPtr = Jim_NewIntObj(interp, wordtokens); + Jim_IncrRefCount(token->objPtr); + token++; + if (wordtokens < 0) { + /* Skip the expand token */ + i++; + wordtokens = -wordtokens - 1; + lineargs--; + } + } + + if (lineargs == 0) { + /* First real token on the line, so record the line number */ + linenr = tokenlist->list[i].line; + } + lineargs++; + + /* Add each non-separator word token to the line */ + while (wordtokens--) { + const ParseToken *t = &tokenlist->list[i++]; + + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + + /* Every object is initially a string, but the + * internal type may be specialized during execution of the + * script. */ + JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); + token++; + } + } + + if (lineargs == 0) { + token--; + } + + script->len = token - script->token; + + assert(script->len < count); + +#ifdef DEBUG_SHOW_SCRIPT + printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); + for (i = 0; i < script->len; i++) { + const ScriptToken *t = &script->token[i]; + printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } +#endif + +} + +/** + * Similar to ScriptObjAddTokens(), but for subst objects. + */ +static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); + + for (i = 0; i < tokenlist->count; i++) { + const ParseToken *t = &tokenlist->list[i]; + + /* Create a token for 't' */ + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + token++; + } + + script->len = i; +} + +/* This method takes the string representation of an object + * as a Tcl script, and generates the pre-parsed internal representation + * of the script. */ +static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script; + ParseTokenList tokenlist; + int line = 1; + + /* Try to get information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + line = objPtr->internalRep.sourceValue.lineNumber; + } + + /* Initially parse the script into tokens (in tokenlist) */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, line); + while (!parser.eof) { + JimParseScript(&parser); + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + if (result && parser.missing != ' ') { + ScriptTokenListFree(&tokenlist); + result->missing = parser.missing; + result->line = parser.missingline; + return JIM_ERR; + } + + /* Add a final EOF token */ + ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); + + /* Create the "real" script tokens from the initial token list */ + script = Jim_Alloc(sizeof(*script)); + memset(script, 0, sizeof(*script)); + script->inUse = 1; + script->line = line; + if (objPtr->typePtr == &sourceObjType) { + script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + } + else { + script->fileNameObj = interp->emptyObj; + } + Jim_IncrRefCount(script->fileNameObj); + + ScriptObjAddTokens(interp, script, &tokenlist); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + + /* Free the old internal rep and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; + + return JIM_OK; +} + +ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) +{ + struct ScriptObj *script = Jim_GetIntRepPtr(objPtr); + + if (objPtr->typePtr != &scriptObjType || script->substFlags) { + SetScriptFromAny(interp, objPtr, NULL); + } + return (ScriptObj *) Jim_GetIntRepPtr(objPtr); +} + +/* ----------------------------------------------------------------------------- + * Commands + * ---------------------------------------------------------------------------*/ +static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) +{ + cmdPtr->inUse++; +} + +static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr) +{ + if (--cmdPtr->inUse == 0) { + if (cmdPtr->isproc) { + Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr); + Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr); + if (cmdPtr->u.proc.staticVars) { + Jim_FreeHashTable(cmdPtr->u.proc.staticVars); + Jim_Free(cmdPtr->u.proc.staticVars); + } + if (cmdPtr->u.proc.prevCmd) { + /* Delete any pushed command too */ + JimDecrCmdRefCount(interp, cmdPtr->u.proc.prevCmd); + } + } + else { + /* native (C) */ + if (cmdPtr->u.native.delProc) { + cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); + } + } + Jim_Free(cmdPtr); + } +} + +/* Commands HashTable Type. + * + * Keys are dynamic allocated strings, Values are Jim_Cmd structures. */ +static void JimCommandsHT_ValDestructor(void *interp, void *val) +{ + JimDecrCmdRefCount(interp, val); +} + +static const Jim_HashTableType JimCommandsHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimCommandsHT_ValDestructor /* val destructor */ +}; + +/* ------------------------- Commands related functions --------------------- */ + +int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName, + Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc) +{ + Jim_Cmd *cmdPtr; + + if (Jim_DeleteHashEntry(&interp->commands, cmdName) != JIM_ERR) { + /* Command existed so incr proc epoch */ + Jim_InterpIncrProcEpoch(interp); + } + + cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); + + /* Store the new details for this proc */ + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->u.native.delProc = delProc; + cmdPtr->u.native.cmdProc = cmdProc; + cmdPtr->u.native.privData = privData; + + Jim_AddHashEntry(&interp->commands, cmdName, cmdPtr); + + /* There is no need to increment the 'proc epoch' because + * creation of a new procedure can never affect existing + * cached commands. We don't do negative caching. */ + return JIM_OK; +} + +static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName, + Jim_Obj *argListObjPtr, Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr) +{ + Jim_Cmd *cmdPtr; + Jim_HashEntry *he; + int argListLen; + int i; + + if (JimValidName(interp, "procedure", cmdName) != JIM_OK) { + return JIM_ERR; + } + + argListLen = Jim_ListLength(interp, argListObjPtr); + + /* Allocate space for both the command pointer and the arg list */ + cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->isproc = 1; + cmdPtr->u.proc.argListObjPtr = argListObjPtr; + cmdPtr->u.proc.argListLen = argListLen; + cmdPtr->u.proc.bodyObjPtr = bodyObjPtr; + cmdPtr->u.proc.argsPos = -1; + cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1); + Jim_IncrRefCount(argListObjPtr); + Jim_IncrRefCount(bodyObjPtr); + + /* Create the statics hash table. */ + if (staticsListObjPtr) { + int len, i; + + len = Jim_ListLength(interp, staticsListObjPtr); + if (len != 0) { + cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); + for (i = 0; i < len; i++) { + Jim_Obj *objPtr = 0, *initObjPtr = 0, *nameObjPtr = 0; + Jim_Var *varPtr; + int subLen; + + Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE); + /* Check if it's composed of two elements. */ + subLen = Jim_ListLength(interp, objPtr); + if (subLen == 1 || subLen == 2) { + /* Try to get the variable value from the current + * environment. */ + Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE); + if (subLen == 1) { + initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); + if (initObjPtr == NULL) { + Jim_SetResultFormatted(interp, + "variable for initialization of static \"%#s\" not found in the local context", + nameObjPtr); + goto err; + } + } + else { + Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE); + } + if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { + goto err; + } + + varPtr = Jim_Alloc(sizeof(*varPtr)); + varPtr->objPtr = initObjPtr; + Jim_IncrRefCount(initObjPtr); + varPtr->linkFramePtr = NULL; + if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars, + Jim_String(nameObjPtr), varPtr) != JIM_OK) { + Jim_SetResultFormatted(interp, + "static variable name \"%#s\" duplicated in statics list", nameObjPtr); + Jim_DecrRefCount(interp, initObjPtr); + Jim_Free(varPtr); + goto err; + } + } + else { + Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"", + objPtr); + goto err; + } + } + } + } + + /* Parse the args out into arglist, validating as we go */ + /* Examine the argument list for default parameters and 'args' */ + for (i = 0; i < argListLen; i++) { + Jim_Obj *argPtr; + Jim_Obj *nameObjPtr; + Jim_Obj *defaultObjPtr; + int len; + int n = 1; + + /* Examine a parameter */ + Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE); + len = Jim_ListLength(interp, argPtr); + if (len == 0) { + Jim_SetResultString(interp, "procedure has argument with no name", -1); + goto err; + } + if (len > 2) { + Jim_SetResultString(interp, "procedure has argument with too many fields", -1); + goto err; + } + + if (len == 2) { + /* Optional parameter */ + Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE); + Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE); + } + else { + /* Required parameter */ + nameObjPtr = argPtr; + defaultObjPtr = NULL; + } + + + if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) { + if (cmdPtr->u.proc.argsPos >= 0) { + Jim_SetResultString(interp, "procedure has 'args' specified more than once", -1); + goto err; + } + cmdPtr->u.proc.argsPos = i; + } + else { + if (len == 2) { + cmdPtr->u.proc.optArity += n; + } + else { + cmdPtr->u.proc.reqArity += n; + } + } + + cmdPtr->u.proc.arglist[i].nameObjPtr = nameObjPtr; + cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr; + } + + /* Add the new command */ + + /* It may already exist, so we try to delete the old one. + * Note that reference count means that it won't be deleted yet if + * it exists in the call stack. + * + * BUT, if 'local' is in force, instead of deleting the existing + * proc, we stash a reference to the old proc here. + */ + he = Jim_FindHashEntry(&interp->commands, Jim_String(cmdName)); + if (he) { + /* There was an old procedure with the same name, this requires + * a 'proc epoch' update. */ + + /* If a procedure with the same name didn't existed there is no need + * to increment the 'proc epoch' because creation of a new procedure + * can never affect existing cached commands. We don't do + * negative caching. */ + Jim_InterpIncrProcEpoch(interp); + } + + if (he && interp->local) { + /* Just push this proc over the top of the previous one */ + cmdPtr->u.proc.prevCmd = he->u.val; + he->u.val = cmdPtr; + } + else { + if (he) { + /* Replace the existing proc */ + Jim_DeleteHashEntry(&interp->commands, Jim_String(cmdName)); + } + + Jim_AddHashEntry(&interp->commands, Jim_String(cmdName), cmdPtr); + } + + /* Unlike Tcl, set the name of the proc as the result */ + Jim_SetResult(interp, cmdName); + return JIM_OK; + + err: + if (cmdPtr->u.proc.staticVars) { + Jim_FreeHashTable(cmdPtr->u.proc.staticVars); + } + Jim_Free(cmdPtr->u.proc.staticVars); + Jim_DecrRefCount(interp, argListObjPtr); + Jim_DecrRefCount(interp, bodyObjPtr); + Jim_Free(cmdPtr); + return JIM_ERR; +} + +int Jim_DeleteCommand(Jim_Interp *interp, const char *cmdName) +{ + if (Jim_DeleteHashEntry(&interp->commands, cmdName) == JIM_ERR) + return JIM_ERR; + Jim_InterpIncrProcEpoch(interp); + return JIM_OK; +} + +int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName) +{ + Jim_HashEntry *he; + + /* Does it exist? */ + he = Jim_FindHashEntry(&interp->commands, oldName); + if (he == NULL) { + Jim_SetResultFormatted(interp, "can't %s \"%s\": command doesn't exist", + newName[0] ? "rename" : "delete", oldName); + return JIM_ERR; + } + + if (newName[0] == '\0') /* Delete! */ + return Jim_DeleteCommand(interp, oldName); + + /* rename */ + if (Jim_FindHashEntry(&interp->commands, newName)) { + Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); + return JIM_ERR; + } + + /* Add the new name first */ + JimIncrCmdRefCount(he->u.val); + Jim_AddHashEntry(&interp->commands, newName, he->u.val); + + /* Now remove the old name */ + Jim_DeleteHashEntry(&interp->commands, oldName); + + /* Increment the epoch */ + Jim_InterpIncrProcEpoch(interp); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Command object + * ---------------------------------------------------------------------------*/ + +static int SetCommandFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType commandObjType = { + "command", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_HashEntry *he; + const char *cmdName; + + /* Get the string representation */ + cmdName = Jim_String(objPtr); + /* Lookup this name into the commands hash table */ + he = Jim_FindHashEntry(&interp->commands, cmdName); + if (he == NULL) + return JIM_ERR; + + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &commandObjType; + objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; + objPtr->internalRep.cmdValue.cmdPtr = (void *)he->u.val; + return JIM_OK; +} + +/* This function returns the command structure for the command name + * stored in objPtr. It tries to specialize the objPtr to contain + * a cached info instead to perform the lookup into the hash table + * every time. The information cached may not be uptodate, in such + * a case the lookup is performed and the cache updated. + * + * Respects the 'upcall' setting + */ +Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + Jim_Cmd *cmd; + + if ((objPtr->typePtr != &commandObjType || + objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch) && + SetCommandFromAny(interp, objPtr) == JIM_ERR) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); + } + return NULL; + } + cmd = objPtr->internalRep.cmdValue.cmdPtr; + while (cmd->isproc && cmd->u.proc.upcall) { + cmd = cmd->u.proc.prevCmd; + } + return cmd; +} + +/* ----------------------------------------------------------------------------- + * Variables + * ---------------------------------------------------------------------------*/ + +/* Variables HashTable Type. + * + * Keys are dynamic allocated strings, Values are Jim_Var structures. */ +static void JimVariablesHTValDestructor(void *interp, void *val) +{ + Jim_Var *varPtr = (void *)val; + + Jim_DecrRefCount(interp, varPtr->objPtr); + Jim_Free(val); +} + +static const Jim_HashTableType JimVariablesHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimVariablesHTValDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Variable object + * ---------------------------------------------------------------------------*/ + +#define JIM_DICT_SUGAR 100 /* Only returned by SetVariableFromAny() */ + +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType variableObjType = { + "variable", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* Return true if the string "str" looks like syntax sugar for [dict]. I.e. + * is in the form "varname(key)". */ +static int JimNameIsDictSugar(const char *str, int len) +{ + if (len && str[len - 1] == ')' && strchr(str, '(') != NULL) + return 1; + return 0; +} + +/** + * Check that the name does not contain embedded nulls. + * + * Variable and procedure names are maniplated as null terminated strings, so + * don't allow names with embedded nulls. + */ +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) +{ + /* Variable names and proc names can't contain embedded nulls */ + if (nameObjPtr->typePtr != &variableObjType) { + int len; + const char *str = Jim_GetString(nameObjPtr, &len); + if (memchr(str, '\0', len)) { + Jim_SetResultFormatted(interp, "%s name contains embedded null", type); + return JIM_ERR; + } + } + return JIM_OK; +} + +/* This method should be called only by the variable API. + * It returns JIM_OK on success (variable already exists), + * JIM_ERR if it does not exists, JIM_DICT_SUGAR if it's not + * a variable name, but syntax glue for [dict] i.e. the last + * character is ')' */ +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + Jim_HashEntry *he; + const char *varName; + int len; + Jim_CallFrame *framePtr = interp->framePtr; + + /* Check if the object is already an uptodate variable */ + if (objPtr->typePtr == &variableObjType && + objPtr->internalRep.varValue.callFrameId == framePtr->id) { + return JIM_OK; /* nothing to do */ + } + + if (objPtr->typePtr == &dictSubstObjType) { + return JIM_DICT_SUGAR; + } + + if (JimValidName(interp, "variable", objPtr) != JIM_OK) { + return JIM_ERR; + } + + /* Get the string representation */ + varName = Jim_GetString(objPtr, &len); + + /* Make sure it's not syntax glue to get/set dict. */ + if (JimNameIsDictSugar(varName, len)) { + return JIM_DICT_SUGAR; + } + + if (varName[0] == ':' && varName[1] == ':') { + framePtr = interp->topFramePtr; + he = Jim_FindHashEntry(&framePtr->vars, varName + 2); + if (he == NULL) { + return JIM_ERR; + } + } + else { + /* Lookup this name into the variables hash table */ + he = Jim_FindHashEntry(&framePtr->vars, varName); + if (he == NULL) { + /* Try with static vars. */ + if (framePtr->staticVars == NULL) + return JIM_ERR; + if (!(he = Jim_FindHashEntry(framePtr->staticVars, varName))) + return JIM_ERR; + } + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &variableObjType; + objPtr->internalRep.varValue.callFrameId = framePtr->id; + objPtr->internalRep.varValue.varPtr = (void *)he->u.val; + return JIM_OK; +} + +/* -------------------- Variables related functions ------------------------- */ +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr); +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags); + +/* For now that's dummy. Variables lookup should be optimized + * in many ways, with caching of lookups, and possibly with + * a table of pre-allocated vars in every CallFrame for local vars. + * All the caching should also have an 'epoch' mechanism similar + * to the one used by Tcl for procedures lookup caching. */ + +int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) +{ + const char *name; + Jim_Var *var; + int err; + + if ((err = SetVariableFromAny(interp, nameObjPtr)) != JIM_OK) { + Jim_CallFrame *framePtr = interp->framePtr; + + /* Check for [dict] syntax sugar. */ + if (err == JIM_DICT_SUGAR) + return JimDictSugarSet(interp, nameObjPtr, valObjPtr); + + if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) { + return JIM_ERR; + } + + /* New variable to create */ + name = Jim_String(nameObjPtr); + + var = Jim_Alloc(sizeof(*var)); + var->objPtr = valObjPtr; + Jim_IncrRefCount(valObjPtr); + var->linkFramePtr = NULL; + /* Insert the new variable */ + if (name[0] == ':' && name[1] == ':') { + /* Into the top level frame */ + framePtr = interp->topFramePtr; + Jim_AddHashEntry(&framePtr->vars, name + 2, var); + } + else { + Jim_AddHashEntry(&framePtr->vars, name, var); + } + /* Make the object int rep a variable */ + Jim_FreeIntRep(interp, nameObjPtr); + nameObjPtr->typePtr = &variableObjType; + nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; + nameObjPtr->internalRep.varValue.varPtr = var; + } + else { + var = nameObjPtr->internalRep.varValue.varPtr; + if (var->linkFramePtr == NULL) { + Jim_IncrRefCount(valObjPtr); + Jim_DecrRefCount(interp, var->objPtr); + var->objPtr = valObjPtr; + } + else { /* Else handle the link */ + Jim_CallFrame *savedCallFrame; + + savedCallFrame = interp->framePtr; + interp->framePtr = var->linkFramePtr; + err = Jim_SetVariable(interp, var->objPtr, valObjPtr); + interp->framePtr = savedCallFrame; + if (err != JIM_OK) + return err; + } + } + return JIM_OK; +} + +int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_Obj *nameObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, objPtr); + Jim_DecrRefCount(interp, nameObjPtr); + return result; +} + +int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_CallFrame *savedFramePtr; + int result; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + result = Jim_SetVariableStr(interp, name, objPtr); + interp->framePtr = savedFramePtr; + return result; +} + +int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) +{ + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + valObjPtr = Jim_NewStringObj(interp, val, -1); + Jim_IncrRefCount(nameObjPtr); + Jim_IncrRefCount(valObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + Jim_DecrRefCount(interp, valObjPtr); + return result; +} + +int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, + Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) +{ + const char *varName; + int len; + + varName = Jim_GetString(nameObjPtr, &len); + + if (varName[0] == ':' && varName[1] == ':') { + /* Linking a global var does nothing */ + return JIM_OK; + } + + if (JimNameIsDictSugar(varName, len)) { + Jim_SetResultString(interp, "Dict key syntax invalid as link source", -1); + return JIM_ERR; + } + + /* Check for an existing variable or link */ + if (SetVariableFromAny(interp, nameObjPtr) == JIM_OK) { + Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); + return JIM_ERR; + } + + /* It exists, but is a link, so delete the link */ + varPtr->linkFramePtr = NULL; + } + + /* Check for cycles. */ + if (interp->framePtr == targetCallFrame) { + Jim_Obj *objPtr = targetNameObjPtr; + Jim_Var *varPtr; + + /* Cycles are only possible with 'uplevel 0' */ + while (1) { + if (Jim_StringEqObj(objPtr, nameObjPtr)) { + Jim_SetResultString(interp, "can't upvar from variable to itself", -1); + return JIM_ERR; + } + if (SetVariableFromAny(interp, objPtr) != JIM_OK) + break; + varPtr = objPtr->internalRep.varValue.varPtr; + if (varPtr->linkFramePtr != targetCallFrame) + break; + objPtr = varPtr->objPtr; + } + } + + /* Perform the binding */ + Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); + /* We are now sure 'nameObjPtr' type is variableObjType */ + nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; + return JIM_OK; +} + +/* Return the Jim_Obj pointer associated with a variable name, + * or NULL if the variable was not found in the current context. + * The same optimization discussed in the comment to the + * 'SetVariable' function should apply here. + * + * If JIM_UNSHARED is set and the variable is an array element (dict sugar) + * in a dictionary which is shared, the array variable value is duplicated first. + * This allows the array element to be updated (e.g. append, lappend) without + * affecting other references to the dictionary. + */ +Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + switch (SetVariableFromAny(interp, nameObjPtr)) { + case JIM_OK:{ + Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + return varPtr->objPtr; + } + else { + Jim_Obj *objPtr; + + /* The variable is a link? Resolve it. */ + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = varPtr->linkFramePtr; + objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); + interp->framePtr = savedCallFrame; + if (objPtr) { + return objPtr; + } + /* Error, so fall through to the error message */ + } + } + break; + + case JIM_DICT_SUGAR: + /* [dict] syntax sugar. */ + return JimDictSugarGet(interp, nameObjPtr, flags); + } + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); + } + return NULL; +} + +Jim_Obj *Jim_GetGlobalVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariable(interp, nameObjPtr, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +Jim_Obj *Jim_GetVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_Obj *nameObjPtr, *varObjPtr; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + varObjPtr = Jim_GetVariable(interp, nameObjPtr, flags); + Jim_DecrRefCount(interp, nameObjPtr); + return varObjPtr; +} + +Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariableStr(interp, name, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +/* Unset a variable. + * Note: On success unset invalidates all the variable objects created + * in the current call frame incrementing. */ +int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + const char *name; + Jim_Var *varPtr; + int retval; + + retval = SetVariableFromAny(interp, nameObjPtr); + if (retval == JIM_DICT_SUGAR) { + /* [dict] syntax sugar. */ + return JimDictSugarSet(interp, nameObjPtr, NULL); + } + else if (retval == JIM_OK) { + varPtr = nameObjPtr->internalRep.varValue.varPtr; + + /* If it's a link call UnsetVariable recursively */ + if (varPtr->linkFramePtr) { + Jim_CallFrame *savedCallFrame; + + savedCallFrame = interp->framePtr; + interp->framePtr = varPtr->linkFramePtr; + retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); + interp->framePtr = savedCallFrame; + } + else { + Jim_CallFrame *framePtr = interp->framePtr; + + name = Jim_String(nameObjPtr); + if (name[0] == ':' && name[1] == ':') { + framePtr = interp->topFramePtr; + name += 2; + } + retval = Jim_DeleteHashEntry(&framePtr->vars, name); + if (retval == JIM_OK) { + /* Change the callframe id, invalidating var lookup caching */ + JimChangeCallFrameId(interp, framePtr); + } + } + } + if (retval != JIM_OK && (flags & JIM_ERRMSG)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); + } + return retval; +} + +/* ---------- Dict syntax sugar (similar to array Tcl syntax) -------------- */ + +/* Given a variable name for [dict] operation syntax sugar, + * this function returns two objects, the first with the name + * of the variable to set, and the second with the rispective key. + * For example "foo(bar)" will return objects with string repr. of + * "foo" and "bar". + * + * The returned objects have refcount = 1. The function can't fail. */ +static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr) +{ + const char *str, *p; + int len, keyLen; + Jim_Obj *varObjPtr, *keyObjPtr; + + str = Jim_GetString(objPtr, &len); + + p = strchr(str, '('); + JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str)); + + varObjPtr = Jim_NewStringObj(interp, str, p - str); + + p++; + keyLen = (str + len) - p; + if (str[len - 1] == ')') { + keyLen--; + } + + /* Create the objects with the variable name and key. */ + keyObjPtr = Jim_NewStringObj(interp, p, keyLen); + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + *varPtrPtr = varObjPtr; + *keyPtrPtr = keyObjPtr; +} + +/* Helper of Jim_SetVariable() to deal with dict-syntax variable names. + * Also used by Jim_UnsetVariable() with valObjPtr = NULL. */ +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr) +{ + int err; + + SetDictSubstFromAny(interp, objPtr); + + err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_ERRMSG); + + if (err == JIM_OK) { + /* Don't keep an extra ref to the result */ + Jim_SetEmptyResult(interp); + } + else { + if (!valObjPtr) { + /* Better error message for unset a(2) where a exists but a(2) doesn't */ + if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", + objPtr); + return err; + } + } + /* Make the error more informative and Tcl-compatible */ + Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", + (valObjPtr ? "set" : "unset"), objPtr); + } + return err; +} + +/** + * Expands the array variable (dict sugar) and returns the result, or NULL on error. + * + * If JIM_UNSHARED is set and the dictionary is shared, it will be duplicated + * and stored back to the variable before expansion. + */ +static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr, + Jim_Obj *keyObjPtr, int flags) +{ + Jim_Obj *dictObjPtr; + Jim_Obj *resObjPtr = NULL; + int ret; + + dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG); + if (!dictObjPtr) { + return NULL; + } + + ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); + if (ret != JIM_OK) { + resObjPtr = NULL; + if (ret < 0) { + Jim_SetResultFormatted(interp, + "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr); + } + else { + Jim_SetResultFormatted(interp, + "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr); + } + } + else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { + dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr); + if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) { + /* This can probably never happen */ + JimPanic((1, "SetVariable failed for JIM_UNSHARED")); + } + /* We know that the key exists. Get the result in the now-unshared dictionary */ + Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); + } + + return resObjPtr; +} + +/* Helper of Jim_GetVariable() to deal with dict-syntax variable names */ +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + SetDictSubstFromAny(interp, objPtr); + + return JimDictExpandArrayVariable(interp, + objPtr->internalRep.dictSubstValue.varNameObjPtr, + objPtr->internalRep.dictSubstValue.indexObjPtr, flags); +} + +/* --------- $var(INDEX) substitution, using a specialized object ----------- */ + +void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); +} + +void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + dupPtr->internalRep.dictSubstValue.varNameObjPtr = + srcPtr->internalRep.dictSubstValue.varNameObjPtr; + dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; + dupPtr->typePtr = &dictSubstObjType; +} + +/* Note: The object *must* be in dict-sugar format */ +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &dictSubstObjType) { + Jim_Obj *varObjPtr, *keyObjPtr; + + if (objPtr->typePtr == &interpolatedObjType) { + /* An interpolated object in dict-sugar form */ + + const ScriptToken *token = objPtr->internalRep.twoPtrValue.ptr1; + + varObjPtr = token[0].objPtr; + keyObjPtr = objPtr->internalRep.twoPtrValue.ptr2; + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + } + else { + JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr); + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictSubstObjType; + objPtr->internalRep.dictSubstValue.varNameObjPtr = varObjPtr; + objPtr->internalRep.dictSubstValue.indexObjPtr = keyObjPtr; + } +} + +/* This function is used to expand [dict get] sugar in the form + * of $var(INDEX). The function is mainly used by Jim_EvalObj() + * to deal with tokens of type JIM_TT_DICTSUGAR. objPtr points to an + * object that is *guaranteed* to be in the form VARNAME(INDEX). + * The 'index' part is [subst]ituted, and is used to lookup a key inside + * the [dict]ionary contained in variable VARNAME. */ +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resObjPtr = NULL; + Jim_Obj *substKeyObjPtr = NULL; + + SetDictSubstFromAny(interp, objPtr); + + if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr, + &substKeyObjPtr, JIM_NONE) + != JIM_OK) { + return NULL; + } + Jim_IncrRefCount(substKeyObjPtr); + resObjPtr = + JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + substKeyObjPtr, 0); + Jim_DecrRefCount(interp, substKeyObjPtr); + + return resObjPtr; +} + +static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resultObjPtr; + + if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { + /* Note that the result has a ref count of 1, but we need a ref count of 0 */ + resultObjPtr->refCount--; + return resultObjPtr; + } + return NULL; +} + +/* ----------------------------------------------------------------------------- + * CallFrame + * ---------------------------------------------------------------------------*/ + +static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent) +{ + Jim_CallFrame *cf; + + if (interp->freeFramesList) { + cf = interp->freeFramesList; + interp->freeFramesList = cf->nextFramePtr; + } + else { + cf = Jim_Alloc(sizeof(*cf)); + cf->vars.table = NULL; + } + + cf->id = interp->callFrameEpoch++; + cf->parentCallFrame = parent; + cf->level = parent ? parent->level + 1 : 0; + cf->argv = NULL; + cf->argc = 0; + cf->procArgsObjPtr = NULL; + cf->procBodyObjPtr = NULL; + cf->nextFramePtr = NULL; + cf->staticVars = NULL; + if (cf->vars.table == NULL) + Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); + return cf; +} + +/* Used to invalidate every caching related to callframe stability. */ +static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf) +{ + cf->id = interp->callFrameEpoch++; +} + +#define JIM_FCF_NONE 0 /* no flags */ +#define JIM_FCF_NOHT 1 /* don't free the hash table */ +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags) +{ + if (cf->procArgsObjPtr) + Jim_DecrRefCount(interp, cf->procArgsObjPtr); + if (cf->procBodyObjPtr) + Jim_DecrRefCount(interp, cf->procBodyObjPtr); + if (!(flags & JIM_FCF_NOHT)) + Jim_FreeHashTable(&cf->vars); + else { + int i; + Jim_HashEntry **table = cf->vars.table, *he; + + for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { + he = table[i]; + while (he != NULL) { + Jim_HashEntry *nextEntry = he->next; + Jim_Var *varPtr = (void *)he->u.val; + + Jim_DecrRefCount(interp, varPtr->objPtr); + Jim_Free(he->u.val); + Jim_Free((void *)he->key); /* ATTENTION: const cast */ + Jim_Free(he); + table[i] = NULL; + he = nextEntry; + } + } + cf->vars.used = 0; + } + cf->nextFramePtr = interp->freeFramesList; + interp->freeFramesList = cf; +} + +/* ----------------------------------------------------------------------------- + * References + * ---------------------------------------------------------------------------*/ +#ifdef JIM_REFERENCES + +/* References HashTable Type. + * + * Keys are jim_wide integers, dynamically allocated for now but in the + * future it's worth to cache this 8 bytes objects. Values are poitners + * to Jim_References. */ +static void JimReferencesHTValDestructor(void *interp, void *val) +{ + Jim_Reference *refPtr = (void *)val; + + Jim_DecrRefCount(interp, refPtr->objPtr); + if (refPtr->finalizerCmdNamePtr != NULL) { + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + } + Jim_Free(val); +} + +static unsigned int JimReferencesHTHashFunction(const void *key) +{ + /* Only the least significant bits are used. */ + const jim_wide *widePtr = key; + unsigned int intValue = (unsigned int)*widePtr; + + return Jim_IntHashFunction(intValue); +} + +static const void *JimReferencesHTKeyDup(void *privdata, const void *key) +{ + void *copy = Jim_Alloc(sizeof(jim_wide)); + + JIM_NOTUSED(privdata); + + memcpy(copy, key, sizeof(jim_wide)); + return copy; +} + +static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return memcmp(key1, key2, sizeof(jim_wide)) == 0; +} + +static void JimReferencesHTKeyDestructor(void *privdata, const void *key) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)key); +} + +static const Jim_HashTableType JimReferencesHashTableType = { + JimReferencesHTHashFunction, /* hash function */ + JimReferencesHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimReferencesHTKeyCompare, /* key compare */ + JimReferencesHTKeyDestructor, /* key destructor */ + JimReferencesHTValDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Reference object type and References API + * ---------------------------------------------------------------------------*/ + +/* The string representation of references has two features in order + * to make the GC faster. The first is that every reference starts + * with a non common character '<', in order to make the string matching + * faster. The second is that the reference string rep is 42 characters + * in length, this allows to avoid to check every object with a string + * repr < 42, and usually there aren't many of these objects. */ + +#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) + +static int JimFormatReference(char *buf, Jim_Reference *refPtr, jim_wide id) +{ + const char *fmt = "<reference.<%s>.%020" JIM_WIDE_MODIFIER ">"; + + sprintf(buf, fmt, refPtr->tag, id); + return JIM_REFERENCE_SPACE; +} + +static void UpdateStringOfReference(struct Jim_Obj *objPtr); + +static const Jim_ObjType referenceObjType = { + "reference", + NULL, + NULL, + UpdateStringOfReference, + JIM_TYPE_REFERENCES, +}; + +void UpdateStringOfReference(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_REFERENCE_SPACE + 1]; + Jim_Reference *refPtr; + + refPtr = objPtr->internalRep.refValue.refPtr; + len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +/* returns true if 'c' is a valid reference tag character. + * i.e. inside the range [_a-zA-Z0-9] */ +static int isrefchar(int c) +{ + return (c == '_' || isalnum(c)); +} + +static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + jim_wide wideValue; + int i, len; + const char *str, *start, *end; + char refId[21]; + Jim_Reference *refPtr; + Jim_HashEntry *he; + + /* Get the string representation */ + str = Jim_GetString(objPtr, &len); + /* Check if it looks like a reference */ + if (len < JIM_REFERENCE_SPACE) + goto badformat; + /* Trim spaces */ + start = str; + end = str + len - 1; + while (*start == ' ') + start++; + while (*end == ' ' && end > start) + end--; + if (end - start + 1 != JIM_REFERENCE_SPACE) + goto badformat; + /* <reference.<1234567>.%020> */ + if (memcmp(start, "<reference.<", 12) != 0) + goto badformat; + if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>') + goto badformat; + /* The tag can't contain chars other than a-zA-Z0-9 + '_'. */ + for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { + if (!isrefchar(start[12 + i])) + goto badformat; + } + /* Extract info from the reference. */ + memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20); + refId[20] = '\0'; + /* Try to convert the ID into a jim_wide */ + if (Jim_StringToWide(refId, &wideValue, 10) != JIM_OK) + goto badformat; + /* Check if the reference really exists! */ + he = Jim_FindHashEntry(&interp->references, &wideValue); + if (he == NULL) { + Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); + return JIM_ERR; + } + refPtr = he->u.val; + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &referenceObjType; + objPtr->internalRep.refValue.id = wideValue; + objPtr->internalRep.refValue.refPtr = refPtr; + return JIM_OK; + + badformat: + Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); + return JIM_ERR; +} + +/* Returns a new reference pointing to objPtr, having cmdNamePtr + * as finalizer command (or NULL if there is no finalizer). + * The returned reference object has refcount = 0. */ +Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) +{ + struct Jim_Reference *refPtr; + jim_wide wideValue = interp->referenceNextId; + Jim_Obj *refObjPtr; + const char *tag; + int tagLen, i; + + /* Perform the Garbage Collection if needed. */ + Jim_CollectIfNeeded(interp); + + refPtr = Jim_Alloc(sizeof(*refPtr)); + refPtr->objPtr = objPtr; + Jim_IncrRefCount(objPtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + if (cmdNamePtr) + Jim_IncrRefCount(cmdNamePtr); + Jim_AddHashEntry(&interp->references, &wideValue, refPtr); + refObjPtr = Jim_NewObj(interp); + refObjPtr->typePtr = &referenceObjType; + refObjPtr->bytes = NULL; + refObjPtr->internalRep.refValue.id = interp->referenceNextId; + refObjPtr->internalRep.refValue.refPtr = refPtr; + interp->referenceNextId++; + /* Set the tag. Trimmed at JIM_REFERENCE_TAGLEN. Everything + * that does not pass the 'isrefchar' test is replaced with '_' */ + tag = Jim_GetString(tagPtr, &tagLen); + if (tagLen > JIM_REFERENCE_TAGLEN) + tagLen = JIM_REFERENCE_TAGLEN; + for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { + if (i < tagLen && isrefchar(tag[i])) + refPtr->tag[i] = tag[i]; + else + refPtr->tag[i] = '_'; + } + refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; + return refObjPtr; +} + +Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) + return NULL; + return objPtr->internalRep.refValue.refPtr; +} + +int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + Jim_IncrRefCount(cmdNamePtr); + if (refPtr->finalizerCmdNamePtr) + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + return JIM_OK; +} + +int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * References Garbage Collection + * ---------------------------------------------------------------------------*/ + +/* This the hash table type for the "MARK" phase of the GC */ +static const Jim_HashTableType JimRefMarkHashTableType = { + JimReferencesHTHashFunction, /* hash function */ + JimReferencesHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimReferencesHTKeyCompare, /* key compare */ + JimReferencesHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; + +/* Performs the garbage collection. */ +int Jim_Collect(Jim_Interp *interp) +{ + int collected = 0; +#ifndef JIM_BOOTSTRAP + Jim_HashTable marks; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *objPtr; + + /* Avoid recursive calls */ + if (interp->lastCollectId == -1) { + /* Jim_Collect() already running. Return just now. */ + return 0; + } + interp->lastCollectId = -1; + + /* Mark all the references found into the 'mark' hash table. + * The references are searched in every live object that + * is of a type that can contain references. */ + Jim_InitHashTable(&marks, &JimRefMarkHashTableType, NULL); + objPtr = interp->liveList; + while (objPtr) { + if (objPtr->typePtr == NULL || objPtr->typePtr->flags & JIM_TYPE_REFERENCES) { + const char *str, *p; + int len; + + /* If the object is of type reference, to get the + * Id is simple... */ + if (objPtr->typePtr == &referenceObjType) { + Jim_AddHashEntry(&marks, &objPtr->internalRep.refValue.id, NULL); +#ifdef JIM_DEBUG_GC + printf("MARK (reference): %d refcount: %d" JIM_NL, + (int)objPtr->internalRep.refValue.id, objPtr->refCount); +#endif + objPtr = objPtr->nextObjPtr; + continue; + } + /* Get the string repr of the object we want + * to scan for references. */ + p = str = Jim_GetString(objPtr, &len); + /* Skip objects too little to contain references. */ + if (len < JIM_REFERENCE_SPACE) { + objPtr = objPtr->nextObjPtr; + continue; + } + /* Extract references from the object string repr. */ + while (1) { + int i; + jim_wide id; + char buf[21]; + + if ((p = strstr(p, "<reference.<")) == NULL) + break; + /* Check if it's a valid reference. */ + if (len - (p - str) < JIM_REFERENCE_SPACE) + break; + if (p[41] != '>' || p[19] != '>' || p[20] != '.') + break; + for (i = 21; i <= 40; i++) + if (!isdigit(UCHAR(p[i]))) + break; + /* Get the ID */ + memcpy(buf, p + 21, 20); + buf[20] = '\0'; + Jim_StringToWide(buf, &id, 10); + + /* Ok, a reference for the given ID + * was found. Mark it. */ + Jim_AddHashEntry(&marks, &id, NULL); +#ifdef JIM_DEBUG_GC + printf("MARK: %d" JIM_NL, (int)id); +#endif + p += JIM_REFERENCE_SPACE; + } + } + objPtr = objPtr->nextObjPtr; + } + + /* Run the references hash table to destroy every reference that + * is not referenced outside (not present in the mark HT). */ + htiter = Jim_GetHashTableIterator(&interp->references); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + const jim_wide *refId; + Jim_Reference *refPtr; + + refId = he->key; + /* Check if in the mark phase we encountered + * this reference. */ + if (Jim_FindHashEntry(&marks, refId) == NULL) { +#ifdef JIM_DEBUG_GC + printf("COLLECTING %d" JIM_NL, (int)*refId); +#endif + collected++; + /* Drop the reference, but call the + * finalizer first if registered. */ + refPtr = he->u.val; + if (refPtr->finalizerCmdNamePtr) { + char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1); + Jim_Obj *objv[3], *oldResult; + + JimFormatReference(refstr, refPtr, *refId); + + objv[0] = refPtr->finalizerCmdNamePtr; + objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, 32); + objv[2] = refPtr->objPtr; + Jim_IncrRefCount(objv[0]); + Jim_IncrRefCount(objv[1]); + Jim_IncrRefCount(objv[2]); + + /* Drop the reference itself */ + Jim_DeleteHashEntry(&interp->references, refId); + + /* Call the finalizer. Errors ignored. */ + oldResult = interp->result; + Jim_IncrRefCount(oldResult); + Jim_EvalObjVector(interp, 3, objv); + Jim_SetResult(interp, oldResult); + Jim_DecrRefCount(interp, oldResult); + + Jim_DecrRefCount(interp, objv[0]); + Jim_DecrRefCount(interp, objv[1]); + Jim_DecrRefCount(interp, objv[2]); + } + else { + Jim_DeleteHashEntry(&interp->references, refId); + } + } + } + Jim_FreeHashTableIterator(htiter); + Jim_FreeHashTable(&marks); + interp->lastCollectId = interp->referenceNextId; + interp->lastCollectTime = time(NULL); +#endif /* JIM_BOOTSTRAP */ + return collected; +} + +#define JIM_COLLECT_ID_PERIOD 5000 +#define JIM_COLLECT_TIME_PERIOD 300 + +void Jim_CollectIfNeeded(Jim_Interp *interp) +{ + jim_wide elapsedId; + int elapsedTime; + + elapsedId = interp->referenceNextId - interp->lastCollectId; + elapsedTime = time(NULL) - interp->lastCollectTime; + + + if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { + Jim_Collect(interp); + } +} +#endif + +static int JimIsBigEndian(void) +{ + union { + unsigned short s; + unsigned char c[2]; + } uval = {0x0102}; + + return uval.c[0] == 1; +} + +/* ----------------------------------------------------------------------------- + * Interpreter related functions + * ---------------------------------------------------------------------------*/ + +Jim_Interp *Jim_CreateInterp(void) +{ + Jim_Interp *i = Jim_Alloc(sizeof(*i)); + + memset(i, 0, sizeof(*i)); + + i->maxNestingDepth = JIM_MAX_NESTING_DEPTH; + i->lastCollectTime = time(NULL); + + /* Note that we can create objects only after the + * interpreter liveList and freeList pointers are + * initialized to NULL. */ + Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i); +#ifdef JIM_REFERENCES + Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); +#endif + Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); + Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL); + i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL); + i->emptyObj = Jim_NewEmptyStringObj(i); + i->trueObj = Jim_NewIntObj(i, 1); + i->falseObj = Jim_NewIntObj(i, 0); + i->errorFileNameObj = i->emptyObj; + i->result = i->emptyObj; + i->stackTrace = Jim_NewListObj(i, NULL, 0); + i->unknown = Jim_NewStringObj(i, "unknown", -1); + i->errorProc = i->emptyObj; + i->currentScriptObj = Jim_NewEmptyStringObj(i); + Jim_IncrRefCount(i->emptyObj); + Jim_IncrRefCount(i->errorFileNameObj); + Jim_IncrRefCount(i->result); + Jim_IncrRefCount(i->stackTrace); + Jim_IncrRefCount(i->unknown); + Jim_IncrRefCount(i->currentScriptObj); + Jim_IncrRefCount(i->errorProc); + Jim_IncrRefCount(i->trueObj); + Jim_IncrRefCount(i->falseObj); + + /* Initialize key variables every interpreter should contain */ + Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); + Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); + + Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); + Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); + Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); + Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian"); + Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); + Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); + Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); + + return i; +} + +void Jim_FreeInterp(Jim_Interp *i) +{ + Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf; + Jim_Obj *objPtr, *nextObjPtr; + + Jim_DecrRefCount(i, i->emptyObj); + Jim_DecrRefCount(i, i->trueObj); + Jim_DecrRefCount(i, i->falseObj); + Jim_DecrRefCount(i, i->result); + Jim_DecrRefCount(i, i->stackTrace); + Jim_DecrRefCount(i, i->errorProc); + Jim_DecrRefCount(i, i->unknown); + Jim_DecrRefCount(i, i->errorFileNameObj); + Jim_DecrRefCount(i, i->currentScriptObj); + Jim_FreeHashTable(&i->commands); +#ifdef JIM_REFERENCES + Jim_FreeHashTable(&i->references); +#endif + Jim_FreeHashTable(&i->packages); + Jim_Free(i->prngState); + Jim_FreeHashTable(&i->assocData); + JimDeleteLocalProcs(i); + + /* Free the call frames list */ + while (cf) { + prevcf = cf->parentCallFrame; + JimFreeCallFrame(i, cf, JIM_FCF_NONE); + cf = prevcf; + } + /* Check that the live object list is empty, otherwise + * there is a memory leak. */ + if (i->liveList != NULL) { + objPtr = i->liveList; + + printf(JIM_NL "-------------------------------------" JIM_NL); + printf("Objects still in the free list:" JIM_NL); + while (objPtr) { + const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; + + printf("%p (%d) %-10s: '%.20s'" JIM_NL, + (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); + if (objPtr->typePtr == &sourceObjType) { + printf("FILE %s LINE %d" JIM_NL, + Jim_String(objPtr->internalRep.sourceValue.fileNameObj), + objPtr->internalRep.sourceValue.lineNumber); + } + objPtr = objPtr->nextObjPtr; + } + printf("-------------------------------------" JIM_NL JIM_NL); + JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); + } + /* Free all the freed objects. */ + objPtr = i->freeList; + while (objPtr) { + nextObjPtr = objPtr->nextObjPtr; + Jim_Free(objPtr); + objPtr = nextObjPtr; + } + /* Free cached CallFrame structures */ + cf = i->freeFramesList; + while (cf) { + nextcf = cf->nextFramePtr; + if (cf->vars.table != NULL) + Jim_Free(cf->vars.table); + Jim_Free(cf); + cf = nextcf; + } +#ifdef jim_ext_load + Jim_FreeLoadHandles(i); +#endif + + /* Free the interpreter structure. */ + Jim_Free(i); +} + +/* Returns the call frame relative to the level represented by + * levelObjPtr. If levelObjPtr == NULL, the * level is assumed to be '1'. + * + * This function accepts the 'level' argument in the form + * of the commands [uplevel] and [upvar]. + * + * For a function accepting a relative integer as level suitable + * for implementation of [info level ?level?] check the + * JimGetCallFrameByInteger() function. + * + * Returns NULL on error. + */ +Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + const char *str; + Jim_CallFrame *framePtr; + + if (levelObjPtr) { + str = Jim_String(levelObjPtr); + if (str[0] == '#') { + char *endptr; + + level = strtol(str + 1, &endptr, 0); + if (str[1] == '\0' || endptr[0] != '\0') { + level = -1; + } + } + else { + if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { + level = -1; + } + else { + /* Convert from a relative to an absolute level */ + level = interp->framePtr->level - level; + } + } + } + else { + str = "1"; /* Needed to format the error message. */ + level = interp->framePtr->level - 1; + } + + if (level == 0) { + return interp->topFramePtr; + } + if (level > 0) { + /* Lookup */ + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%s\"", str); + return NULL; +} + +/* Similar to Jim_GetCallFrameByLevel() but the level is specified + * as a relative integer like in the [info level ?level?] command. + **/ +static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + Jim_CallFrame *framePtr; + + if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { + if (level <= 0) { + /* Convert from a relative to an absolute level */ + level = interp->framePtr->level + level; + } + + if (level == 0) { + return interp->topFramePtr; + } + + /* Lookup */ + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return NULL; +} + +static void JimResetStackTrace(Jim_Interp *interp) +{ + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(interp->stackTrace); +} + +static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) +{ + int len; + + /* Increment reference first in case these are the same object */ + Jim_IncrRefCount(stackTraceObj); + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = stackTraceObj; + interp->errorFlag = 1; + + /* This is a bit ugly. + * If the filename of the last entry of the stack trace is empty, + * the next stack level should be added. + */ + len = Jim_ListLength(interp, interp->stackTrace); + if (len >= 3) { + Jim_Obj *filenameObj; + + Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE); + + Jim_GetString(filenameObj, &len); + + if (!Jim_Length(filenameObj)) { + interp->addStackTrace = 1; + } + } +} + +/* Returns 1 if the stack trace information was used or 0 if not */ +static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, + Jim_Obj *fileNameObj, int linenr) +{ + if (strcmp(procname, "unknown") == 0) { + procname = ""; + } + if (!*procname && !Jim_Length(fileNameObj)) { + /* No useful info here */ + return; + } + + if (Jim_IsShared(interp->stackTrace)) { + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); + Jim_IncrRefCount(interp->stackTrace); + } + + /* If we have no procname but the previous element did, merge with that frame */ + if (!*procname && Jim_Length(fileNameObj)) { + /* Just a filename. Check the previous entry */ + int len = Jim_ListLength(interp, interp->stackTrace); + + if (len >= 3) { + Jim_Obj *objPtr; + if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) { + /* Yes, the previous level had procname */ + if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) { + /* But no filename, so merge the new info with that frame */ + ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); + ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); + return; + } + } + } + } + + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1)); + Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj); + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr)); +} + +int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc, + void *data) +{ + AssocDataValue *assocEntryPtr = (AssocDataValue *) Jim_Alloc(sizeof(AssocDataValue)); + + assocEntryPtr->delProc = delProc; + assocEntryPtr->data = data; + return Jim_AddHashEntry(&interp->assocData, key, assocEntryPtr); +} + +void *Jim_GetAssocData(Jim_Interp *interp, const char *key) +{ + Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); + + if (entryPtr != NULL) { + AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val; + + return assocEntryPtr->data; + } + return NULL; +} + +int Jim_DeleteAssocData(Jim_Interp *interp, const char *key) +{ + return Jim_DeleteHashEntry(&interp->assocData, key); +} + +int Jim_GetExitCode(Jim_Interp *interp) +{ + return interp->exitCode; +} + +/* ----------------------------------------------------------------------------- + * Integer object + * ---------------------------------------------------------------------------*/ +#define JIM_INTEGER_SPACE 24 + +static void UpdateStringOfInt(struct Jim_Obj *objPtr); +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); + +static const Jim_ObjType intObjType = { + "int", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + +/* A coerced double is closer to an int than a double. + * It is an int value temporarily masquerading as a double value. + * i.e. it has the same string value as an int and Jim_GetWide() + * succeeds, but also Jim_GetDouble() returns the value directly. + */ +static const Jim_ObjType coercedDoubleObjType = { + "coerced-double", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + + +void UpdateStringOfInt(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_INTEGER_SPACE + 1]; + + len = Jim_WideToString(buf, JimWideValue(objPtr)); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + jim_wide wideValue; + const char *str; + + if (objPtr->typePtr == &coercedDoubleObjType) { + /* Simple switcheroo */ + objPtr->typePtr = &intObjType; + return JIM_OK; + } + + /* Get the string representation */ + str = Jim_String(objPtr); + /* Try to convert into a jim_wide */ + if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); + } + return JIM_ERR; + } + if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { + Jim_SetResultString(interp, "Integer value too big to be represented", -1); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &intObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; +} + +#ifdef JIM_OPTIMIZATION +static int JimIsWide(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &intObjType; +} +#endif + +int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + +/* Get a wide but does not set an error if the format is bad. */ +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + +int Jim_GetLong(Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr) +{ + jim_wide wideValue; + int retval; + + retval = Jim_GetWide(interp, objPtr, &wideValue); + if (retval == JIM_OK) { + *longPtr = (long)wideValue; + return JIM_OK; + } + return JIM_ERR; +} + +Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &intObjType; + objPtr->bytes = NULL; + objPtr->internalRep.wideValue = wideValue; + return objPtr; +} + +/* ----------------------------------------------------------------------------- + * Double object + * ---------------------------------------------------------------------------*/ +#define JIM_DOUBLE_SPACE 30 + +static void UpdateStringOfDouble(struct Jim_Obj *objPtr); +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr); + +static const Jim_ObjType doubleObjType = { + "double", + NULL, + NULL, + UpdateStringOfDouble, + JIM_TYPE_NONE, +}; + +void UpdateStringOfDouble(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_DOUBLE_SPACE + 1]; + + len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + double doubleValue; + jim_wide wideValue; + const char *str; + + /* Preserve the string representation. + * Needed so we can convert back to int without loss + */ + str = Jim_String(objPtr); + +#ifdef HAVE_LONG_LONG + /* Assume a 53 bit mantissa */ +#define MIN_INT_IN_DOUBLE -(1LL << 53) +#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) + + if (objPtr->typePtr == &intObjType + && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE + && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { + + /* Direct conversion to coerced double */ + objPtr->typePtr = &coercedDoubleObjType; + return JIM_OK; + } + else +#endif + if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { + /* Managed to convert to an int, so we can use this as a cooerced double */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &coercedDoubleObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; + } + else { + /* Try to convert into a double */ + if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected number but got \"%#s\"", objPtr); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + } + objPtr->typePtr = &doubleObjType; + objPtr->internalRep.doubleValue = doubleValue; + return JIM_OK; +} + +int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr) +{ + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + return JIM_OK; + } + if (objPtr->typePtr != &doubleObjType && SetDoubleFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + } + else { + *doublePtr = objPtr->internalRep.doubleValue; + } + return JIM_OK; +} + +Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &doubleObjType; + objPtr->bytes = NULL; + objPtr->internalRep.doubleValue = doubleValue; + return objPtr; +} + +/* ----------------------------------------------------------------------------- + * List object + * ---------------------------------------------------------------------------*/ +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); +static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfList(struct Jim_Obj *objPtr); +static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +/* Note that while the elements of the list may contain references, + * the list object itself can't. This basically means that the + * list object string representation as a whole can't contain references + * that are not presents in the single elements. */ +static const Jim_ObjType listObjType = { + "list", + FreeListInternalRep, + DupListInternalRep, + UpdateStringOfList, + JIM_TYPE_NONE, +}; + +void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + Jim_DecrRefCount(interp, objPtr->internalRep.listValue.ele[i]); + } + Jim_Free(objPtr->internalRep.listValue.ele); +} + +void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + int i; + + JIM_NOTUSED(interp); + + dupPtr->internalRep.listValue.len = srcPtr->internalRep.listValue.len; + dupPtr->internalRep.listValue.maxLen = srcPtr->internalRep.listValue.maxLen; + dupPtr->internalRep.listValue.ele = + Jim_Alloc(sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.maxLen); + memcpy(dupPtr->internalRep.listValue.ele, srcPtr->internalRep.listValue.ele, + sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.len); + for (i = 0; i < dupPtr->internalRep.listValue.len; i++) { + Jim_IncrRefCount(dupPtr->internalRep.listValue.ele[i]); + } + dupPtr->typePtr = &listObjType; +} + +/* The following function checks if a given string can be encoded + * into a list element without any kind of quoting, surrounded by braces, + * or using escapes to quote. */ +#define JIM_ELESTR_SIMPLE 0 +#define JIM_ELESTR_BRACE 1 +#define JIM_ELESTR_QUOTE 2 +static int ListElementQuotingType(const char *s, int len) +{ + int i, level, blevel, trySimple = 1; + + /* Try with the SIMPLE case */ + if (len == 0) + return JIM_ELESTR_BRACE; + if (s[0] == '#') + return JIM_ELESTR_BRACE; + if (s[0] == '"' || s[0] == '{') { + trySimple = 0; + goto testbrace; + } + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + trySimple = 0; + case '{': + case '}': + goto testbrace; + } + } + return JIM_ELESTR_SIMPLE; + + testbrace: + /* Test if it's possible to do with braces */ + if (s[len - 1] == '\\') + return JIM_ELESTR_QUOTE; + level = 0; + blevel = 0; + for (i = 0; i < len; i++) { + switch (s[i]) { + case '{': + level++; + break; + case '}': + level--; + if (level < 0) + return JIM_ELESTR_QUOTE; + break; + case '[': + blevel++; + break; + case ']': + blevel--; + break; + case '\\': + if (s[i + 1] == '\n') + return JIM_ELESTR_QUOTE; + else if (s[i + 1] != '\0') + i++; + break; + } + } + if (blevel < 0) { + return JIM_ELESTR_QUOTE; + } + + if (level == 0) { + if (!trySimple) + return JIM_ELESTR_BRACE; + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + return JIM_ELESTR_BRACE; + break; + } + } + return JIM_ELESTR_SIMPLE; + } + return JIM_ELESTR_QUOTE; +} + +/* Returns the malloc-ed representation of a string + * using backslash to quote special chars. */ +static char *BackslashQuoteString(const char *s, int len, int *qlenPtr) +{ + char *q = Jim_Alloc(len * 2 + 1), *p; + + p = q; + while (*s) { + switch (*s) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case '{': + case '}': + case ';': + case '\\': + *p++ = '\\'; + *p++ = *s++; + break; + case '\n': + *p++ = '\\'; + *p++ = 'n'; + s++; + break; + case '\r': + *p++ = '\\'; + *p++ = 'r'; + s++; + break; + case '\t': + *p++ = '\\'; + *p++ = 't'; + s++; + break; + case '\f': + *p++ = '\\'; + *p++ = 'f'; + s++; + break; + case '\v': + *p++ = '\\'; + *p++ = 'v'; + s++; + break; + default: + *p++ = *s++; + break; + } + } + *p = '\0'; + *qlenPtr = p - q; + return q; +} + +static void UpdateStringOfList(struct Jim_Obj *objPtr) +{ + int i, bufLen, realLength; + const char *strRep; + char *p; + int *quotingType; + Jim_Obj **ele = objPtr->internalRep.listValue.ele; + + /* (Over) Estimate the space needed. */ + quotingType = Jim_Alloc(sizeof(int) * objPtr->internalRep.listValue.len + 1); + bufLen = 0; + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + int len; + + strRep = Jim_GetString(ele[i], &len); + quotingType[i] = ListElementQuotingType(strRep, len); + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + bufLen += len; + break; + case JIM_ELESTR_BRACE: + bufLen += len + 2; + break; + case JIM_ELESTR_QUOTE: + bufLen += len * 2; + break; + } + bufLen++; /* elements separator. */ + } + bufLen++; + + /* Generate the string rep. */ + p = objPtr->bytes = Jim_Alloc(bufLen + 1); + realLength = 0; + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + int len, qlen; + char *q; + + strRep = Jim_GetString(ele[i], &len); + + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + memcpy(p, strRep, len); + p += len; + realLength += len; + break; + case JIM_ELESTR_BRACE: + *p++ = '{'; + memcpy(p, strRep, len); + p += len; + *p++ = '}'; + realLength += len + 2; + break; + case JIM_ELESTR_QUOTE: + q = BackslashQuoteString(strRep, len, &qlen); + memcpy(p, q, qlen); + Jim_Free(q); + p += qlen; + realLength += qlen; + break; + } + /* Add a separating space */ + if (i + 1 != objPtr->internalRep.listValue.len) { + *p++ = ' '; + realLength++; + } + } + *p = '\0'; /* nul term. */ + objPtr->length = realLength; + Jim_Free(quotingType); +} + +int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + struct JimParserCtx parser; + const char *str; + int strLen; + Jim_Obj *fileNameObj; + int linenr; + + /* Try to preserve information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + linenr = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + linenr = 1; + } + Jim_IncrRefCount(fileNameObj); + + /* Get the string representation */ + str = Jim_GetString(objPtr, &strLen); + + /* Free the old internal repr just now and initialize the + * new one just now. The string->list conversion can't fail. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &listObjType; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + objPtr->internalRep.listValue.ele = NULL; + + /* Convert into a list */ + JimParserInit(&parser, str, strLen, linenr); + while (!parser.eof) { + Jim_Obj *elementPtr; + + JimParseList(&parser); + if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC) + continue; + elementPtr = JimParserGetTokenObj(interp, &parser); + JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); + ListAppendElement(objPtr, elementPtr); + } + Jim_DecrRefCount(interp, fileNameObj); + return JIM_OK; +} + +Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + int i; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &listObjType; + objPtr->bytes = NULL; + objPtr->internalRep.listValue.ele = NULL; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + for (i = 0; i < len; i++) { + ListAppendElement(objPtr, elements[i]); + } + return objPtr; +} + +/* Return a vector of Jim_Obj with the elements of a Jim list, and the + * length of the vector. Note that the user of this function should make + * sure that the list object can't shimmer while the vector returned + * is in use, this vector is the one stored inside the internal representation + * of the list object. This function is not exported, extensions should + * always access to the List object elements using Jim_ListIndex(). */ +static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen, + Jim_Obj ***listVec) +{ + *listLen = Jim_ListLength(interp, listObj); + *listVec = listObj->internalRep.listValue.ele; +} + +/* Sorting uses ints, but commands may return wide */ +static int JimSign(jim_wide w) +{ + if (w == 0) { + return 0; + } + else if (w < 0) { + return -1; + } + return 1; +} + +/* ListSortElements type values */ +struct lsort_info { + jmp_buf jmpbuf; + Jim_Obj *command; + Jim_Interp *interp; + enum { + JIM_LSORT_ASCII, + JIM_LSORT_NOCASE, + JIM_LSORT_INTEGER, + JIM_LSORT_COMMAND + } type; + int order; + int index; + int indexed; + int (*subfn)(Jim_Obj **, Jim_Obj **); +}; + +static struct lsort_info *sort_info; + +static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *lObj, *rObj; + + if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK || + Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + return sort_info->subfn(&lObj, &rObj); +} + +/* Sort the internal rep of a list. */ +static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order; +} + +static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order; +} + +static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + jim_wide lhs = 0, rhs = 0; + + if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK || + Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + + return JimSign(lhs - rhs) * sort_info->order; +} + +static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *compare_script; + int rc; + + jim_wide ret = 0; + + /* This must be a valid list */ + compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); + Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); + Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); + + rc = Jim_EvalObj(sort_info->interp, compare_script); + + if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) { + longjmp(sort_info->jmpbuf, rc); + } + + return JimSign(ret) * sort_info->order; +} + +/* Sort a list *in place*. MUST be called with non-shared objects. */ +static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) +{ + struct lsort_info *prev_info; + + typedef int (qsort_comparator) (const void *, const void *); + int (*fn) (Jim_Obj **, Jim_Obj **); + Jim_Obj **vector; + int len; + int rc; + + JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object")); + if (!Jim_IsList(listObjPtr)) + SetListFromAny(interp, listObjPtr); + + /* Allow lsort to be called reentrantly */ + prev_info = sort_info; + sort_info = info; + + vector = listObjPtr->internalRep.listValue.ele; + len = listObjPtr->internalRep.listValue.len; + switch (info->type) { + case JIM_LSORT_ASCII: + fn = ListSortString; + break; + case JIM_LSORT_NOCASE: + fn = ListSortStringNoCase; + break; + case JIM_LSORT_INTEGER: + fn = ListSortInteger; + break; + case JIM_LSORT_COMMAND: + fn = ListSortCommand; + break; + default: + fn = NULL; /* avoid warning */ + JimPanic((1, "ListSort called with invalid sort type")); + } + + if (info->indexed) { + /* Need to interpose a "list index" function */ + info->subfn = fn; + fn = ListSortIndexHelper; + } + + if ((rc = setjmp(info->jmpbuf)) == 0) { + qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); + } + Jim_InvalidateStringRep(listObjPtr); + sort_info = prev_info; + + return rc; +} + +/* This is the low-level function to insert elements into a list. + * The higher-level Jim_ListInsertElements() performs shared object + * check and invalidate the string repr. This version is used + * in the internals of the List Object and is not exported. + * + * NOTE: this function can be called only against objects + * with internal type of List. */ +static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec) +{ + int currentLen = listPtr->internalRep.listValue.len; + int requiredLen = currentLen + elemc; + int i; + Jim_Obj **point; + + if (requiredLen > listPtr->internalRep.listValue.maxLen) { + int maxLen = requiredLen * 2; + + listPtr->internalRep.listValue.ele = + Jim_Realloc(listPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * maxLen); + listPtr->internalRep.listValue.maxLen = maxLen; + } + point = listPtr->internalRep.listValue.ele + idx; + memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *)); + for (i = 0; i < elemc; ++i) { + point[i] = elemVec[i]; + Jim_IncrRefCount(point[i]); + } + listPtr->internalRep.listValue.len += elemc; +} + +/* Convenience call to ListInsertElements() to append a single element. + */ +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + ListInsertElements(listPtr, listPtr->internalRep.listValue.len, 1, &objPtr); +} + + +/* Appends every element of appendListPtr into listPtr. + * Both have to be of the list type. + * Convenience call to ListInsertElements() + */ +static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + ListInsertElements(listPtr, listPtr->internalRep.listValue.len, + appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele); +} + +void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendElement(listPtr, objPtr); +} + +void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendList(listPtr, appendListPtr); +} + +int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (!Jim_IsList(objPtr)) + SetListFromAny(interp, objPtr); + return objPtr->internalRep.listValue.len; +} + +void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + int objc, Jim_Obj *const *objVec) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if (idx >= 0 && idx > listPtr->internalRep.listValue.len) + idx = listPtr->internalRep.listValue.len; + else if (idx < 0) + idx = 0; + Jim_InvalidateStringRep(listPtr); + ListInsertElements(listPtr, idx, objc, objVec); +} + +int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags) +{ + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + *objPtrPtr = NULL; + return JIM_ERR; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + *objPtrPtr = listPtr->internalRep.listValue.ele[idx]; + return JIM_OK; +} + +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + Jim_Obj *newObjPtr, int flags) +{ + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + return JIM_ERR; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]); + listPtr->internalRep.listValue.ele[idx] = newObjPtr; + Jim_IncrRefCount(newObjPtr); + return JIM_OK; +} + +/* Modify the list stored into the variable named 'varNamePtr' + * setting the element specified by the 'indexc' indexes objects in 'indexv', + * with the new element 'newObjptr'. */ +int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) +{ + Jim_Obj *varObjPtr, *objPtr, *listObjPtr; + int shared, i, idx; + + varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED); + if (objPtr == NULL) + return JIM_ERR; + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < indexc - 1; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK) + goto err; + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) { + goto err; + } + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE); + } + Jim_InvalidateStringRep(listObjPtr); + } + if (Jim_GetIndex(interp, indexv[indexc - 1], &idx) != JIM_OK) + goto err; + if (ListSetIndex(interp, objPtr, idx, newObjPtr, JIM_ERRMSG) == JIM_ERR) + goto err; + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) + goto err; + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + int i; + + /* If all the objects in objv are lists, + * it's possible to return a list as result, that's the + * concatenation of all the lists. */ + for (i = 0; i < objc; i++) { + if (!Jim_IsList(objv[i])) + break; + } + if (i == objc) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < objc; i++) + Jim_ListAppendList(interp, objPtr, objv[i]); + return objPtr; + } + else { + /* Else... we have to glue strings together */ + int len = 0, objLen; + char *bytes, *p; + + /* Compute the length */ + for (i = 0; i < objc; i++) { + Jim_GetString(objv[i], &objLen); + len += objLen; + } + if (objc) + len += objc - 1; + /* Create the string rep, and a string object holding it. */ + p = bytes = Jim_Alloc(len + 1); + for (i = 0; i < objc; i++) { + const char *s = Jim_GetString(objv[i], &objLen); + + /* Remove leading space */ + while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) { + s++; + objLen--; + len--; + } + /* And trailing space */ + while (objLen && (s[objLen - 1] == ' ' || + s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) { + /* Handle trailing backslash-space case */ + if (objLen > 1 && s[objLen - 2] == '\\') { + break; + } + objLen--; + len--; + } + memcpy(p, s, objLen); + p += objLen; + if (objLen && i + 1 != objc) { + *p++ = ' '; + } + else if (i + 1 != objc) { + /* Drop the space calcuated for this + * element that is instead null. */ + len--; + } + } + *p = '\0'; + return Jim_NewStringObjNoAlloc(interp, bytes, len); + } +} + +/* Returns a list composed of the elements in the specified range. + * first and start are directly accepted as Jim_Objects and + * processed for the end?-index? case. */ +Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr) +{ + int first, last; + int len, rangeLen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + len = Jim_ListLength(interp, listObjPtr); /* will convert into list */ + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + if (first == 0 && last == len) { + return listObjPtr; + } + return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen); +} + +/* ----------------------------------------------------------------------------- + * Dict object + * ---------------------------------------------------------------------------*/ +static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfDict(struct Jim_Obj *objPtr); +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +/* Dict HashTable Type. + * + * Keys and Values are Jim objects. */ + +static unsigned int JimObjectHTHashFunction(const void *key) +{ + const char *str; + Jim_Obj *objPtr = (Jim_Obj *)key; + int len; + + str = Jim_GetString(objPtr, &len); + return Jim_GenHashFunction((unsigned char *)str, len); +} + +static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); +} + +static void JimObjectHTKeyValDestructor(void *interp, void *val) +{ + Jim_Obj *objPtr = val; + + Jim_DecrRefCount(interp, objPtr); +} + +static const Jim_HashTableType JimDictHashTableType = { + JimObjectHTHashFunction, /* hash function */ + NULL, /* key dup */ + NULL, /* val dup */ + JimObjectHTKeyCompare, /* key compare */ + (void (*)(void *, const void *)) /* ATTENTION: const cast */ + JimObjectHTKeyValDestructor, /* key destructor */ + JimObjectHTKeyValDestructor /* val destructor */ +}; + +/* Note that while the elements of the dict may contain references, + * the list object itself can't. This basically means that the + * dict object string representation as a whole can't contain references + * that are not presents in the single elements. */ +static const Jim_ObjType dictObjType = { + "dict", + FreeDictInternalRep, + DupDictInternalRep, + UpdateStringOfDict, + JIM_TYPE_NONE, +}; + +void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + + Jim_FreeHashTable(objPtr->internalRep.ptr); + Jim_Free(objPtr->internalRep.ptr); +} + +void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + Jim_HashTable *ht, *dupHt; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + + /* Create a new hash table */ + ht = srcPtr->internalRep.ptr; + dupHt = Jim_Alloc(sizeof(*dupHt)); + Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); + if (ht->size != 0) + Jim_ExpandHashTable(dupHt, ht->size); + /* Copy every element from the source to the dup hash table */ + htiter = Jim_GetHashTableIterator(ht); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + const Jim_Obj *keyObjPtr = he->key; + Jim_Obj *valObjPtr = he->u.val; + + Jim_IncrRefCount((Jim_Obj *)keyObjPtr); /* ATTENTION: const cast */ + Jim_IncrRefCount(valObjPtr); + Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); + } + Jim_FreeHashTableIterator(htiter); + + dupPtr->internalRep.ptr = dupHt; + dupPtr->typePtr = &dictObjType; +} + +void UpdateStringOfDict(struct Jim_Obj *objPtr) +{ + int i, bufLen, realLength; + const char *strRep; + char *p; + int *quotingType, objc; + Jim_HashTable *ht; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj **objv; + + /* Trun the hash table into a flat vector of Jim_Objects. */ + ht = objPtr->internalRep.ptr; + objc = ht->used * 2; + objv = Jim_Alloc(objc * sizeof(Jim_Obj *)); + htiter = Jim_GetHashTableIterator(ht); + i = 0; + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */ + objv[i++] = he->u.val; + } + Jim_FreeHashTableIterator(htiter); + /* (Over) Estimate the space needed. */ + quotingType = Jim_Alloc(sizeof(int) * objc); + bufLen = 0; + for (i = 0; i < objc; i++) { + int len; + + strRep = Jim_GetString(objv[i], &len); + quotingType[i] = ListElementQuotingType(strRep, len); + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + bufLen += len; + break; + case JIM_ELESTR_BRACE: + bufLen += len + 2; + break; + case JIM_ELESTR_QUOTE: + bufLen += len * 2; + break; + } + bufLen++; /* elements separator. */ + } + bufLen++; + + /* Generate the string rep. */ + p = objPtr->bytes = Jim_Alloc(bufLen + 1); + realLength = 0; + for (i = 0; i < objc; i++) { + int len, qlen; + char *q; + + strRep = Jim_GetString(objv[i], &len); + + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + memcpy(p, strRep, len); + p += len; + realLength += len; + break; + case JIM_ELESTR_BRACE: + *p++ = '{'; + memcpy(p, strRep, len); + p += len; + *p++ = '}'; + realLength += len + 2; + break; + case JIM_ELESTR_QUOTE: + q = BackslashQuoteString(strRep, len, &qlen); + memcpy(p, q, qlen); + Jim_Free(q); + p += qlen; + realLength += qlen; + break; + } + /* Add a separating space */ + if (i + 1 != objc) { + *p++ = ' '; + realLength++; + } + } + *p = '\0'; /* nul term. */ + objPtr->length = realLength; + Jim_Free(quotingType); + Jim_Free(objv); +} + +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int listlen; + + /* Get the string representation. Do this first so we don't + * change order in case of fast conversion to dict. + */ + Jim_String(objPtr); + + /* For simplicity, convert a non-list object to a list and then to a dict */ + listlen = Jim_ListLength(interp, objPtr); + if (listlen % 2) { + Jim_SetResultString(interp, + "invalid dictionary value: must be a list with an even number of elements", -1); + return JIM_ERR; + } + else { + /* Now it is easy to convert to a dict from a list, and it can't fail */ + Jim_HashTable *ht; + int i; + + ht = Jim_Alloc(sizeof(*ht)); + Jim_InitHashTable(ht, &JimDictHashTableType, interp); + + for (i = 0; i < listlen; i += 2) { + Jim_Obj *keyObjPtr; + Jim_Obj *valObjPtr; + + Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE); + Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE); + + Jim_IncrRefCount(keyObjPtr); + Jim_IncrRefCount(valObjPtr); + + if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) { + Jim_HashEntry *he; + + he = Jim_FindHashEntry(ht, keyObjPtr); + Jim_DecrRefCount(interp, keyObjPtr); + /* ATTENTION: const cast */ + Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); + he->u.val = valObjPtr; + } + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictObjType; + objPtr->internalRep.ptr = ht; + + return JIM_OK; + } +} + +/* Dict object API */ + +/* Add an element to a dict. objPtr must be of the "dict" type. + * The higer-level exported function is Jim_DictAddElement(). + * If an element with the specified key already exists, the value + * associated is replaced with the new one. + * + * if valueObjPtr == NULL, the key is instead removed if it exists. */ +static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + Jim_HashTable *ht = objPtr->internalRep.ptr; + + if (valueObjPtr == NULL) { /* unset */ + return Jim_DeleteHashEntry(ht, keyObjPtr); + } + Jim_IncrRefCount(keyObjPtr); + Jim_IncrRefCount(valueObjPtr); + if (Jim_AddHashEntry(ht, keyObjPtr, valueObjPtr) != JIM_OK) { + Jim_HashEntry *he = Jim_FindHashEntry(ht, keyObjPtr); + + Jim_DecrRefCount(interp, keyObjPtr); + /* ATTENTION: const cast */ + Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); + he->u.val = valueObjPtr; + } + return JIM_OK; +} + +/* Add an element, higher-level interface for DictAddElement(). + * If valueObjPtr == NULL, the key is removed if it exists. */ +int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + int retcode; + + JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); + if (objPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, objPtr) != JIM_OK) + return JIM_ERR; + } + retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); + Jim_InvalidateStringRep(objPtr); + return retcode; +} + +Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + int i; + + JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even")); + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &dictObjType; + objPtr->bytes = NULL; + objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp); + for (i = 0; i < len; i += 2) + DictAddElement(interp, objPtr, elements[i], elements[i + 1]); + return objPtr; +} + +/* Return the value associated to the specified dict key + * Note: Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value + */ +int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, + Jim_Obj **objPtrPtr, int flags) +{ + Jim_HashEntry *he; + Jim_HashTable *ht; + + if (dictPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictPtr) != JIM_OK) + return -1; + } + ht = dictPtr->internalRep.ptr; + if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "key \"%#s\" not found in dictionary", keyPtr); + } + return JIM_ERR; + } + *objPtrPtr = he->u.val; + return JIM_OK; +} + +/* Return an allocated array of key/value pairs for the dictionary. Stores the length in *len */ +int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) +{ + Jim_HashTable *ht; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj **objv; + int i; + + if (dictPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictPtr) != JIM_OK) + return JIM_ERR; + } + ht = dictPtr->internalRep.ptr; + + /* Turn the hash table into a flat vector of Jim_Objects. */ + objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); + htiter = Jim_GetHashTableIterator(ht); + i = 0; + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */ + objv[i++] = he->u.val; + } + *len = i; + Jim_FreeHashTableIterator(htiter); + *objPtrPtr = objv; + return JIM_OK; +} + + +/* Return the value associated to the specified dict keys */ +int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags) +{ + int i; + + if (keyc == 0) { + *objPtrPtr = dictPtr; + return JIM_OK; + } + + for (i = 0; i < keyc; i++) { + Jim_Obj *objPtr; + + if (Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags) + != JIM_OK) + return JIM_ERR; + dictPtr = objPtr; + } + *objPtrPtr = dictPtr; + return JIM_OK; +} + +/* Modify the dict stored into the variable named 'varNamePtr' + * setting the element specified by the 'keyc' keys objects in 'keyv', + * with the new value of the element 'newObjPtr'. + * + * If newObjPtr == NULL the operation is to remove the given key + * from the dictionary. + * + * If flags & JIM_ERRMSG, then failure to remove the key is considered an error + * and JIM_ERR is returned. Otherwise it is ignored and JIM_OK is returned. + */ +int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags) +{ + Jim_Obj *varObjPtr, *objPtr, *dictObjPtr; + int shared, i; + + varObjPtr = objPtr = + Jim_GetVariable(interp, varNamePtr, newObjPtr == NULL ? JIM_ERRMSG : JIM_NONE); + if (objPtr == NULL) { + if (newObjPtr == NULL) /* Cannot remove a key from non existing var */ { + return JIM_ERR; + } + varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); + if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, varObjPtr); + return JIM_ERR; + } + } + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < keyc - 1; i++) { + dictObjPtr = objPtr; + + /* Check if it's a valid dictionary */ + if (dictObjPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { + goto err; + } + } + /* Check if the given key exists. */ + Jim_InvalidateStringRep(dictObjPtr); + if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, + newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { + /* This key exists at the current level. + * Make sure it's not shared!. */ + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + else { + /* Key not found. If it's an [unset] operation + * this is an error. Only the last key may not + * exist. */ + if (newObjPtr == NULL) { + goto err; + } + /* Otherwise set an empty dictionary + * as key's value. */ + objPtr = Jim_NewDictObj(interp, NULL, 0); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + /* Note error on unset with missing last key is OK */ + if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { + if (newObjPtr || (flags & JIM_ERRMSG)) { + goto err; + } + } + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { + goto err; + } + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +/* ----------------------------------------------------------------------------- + * Index object + * ---------------------------------------------------------------------------*/ +static void UpdateStringOfIndex(struct Jim_Obj *objPtr); +static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType indexObjType = { + "index", + NULL, + NULL, + UpdateStringOfIndex, + JIM_TYPE_NONE, +}; + +void UpdateStringOfIndex(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_INTEGER_SPACE + 1]; + + if (objPtr->internalRep.indexValue >= 0) + len = sprintf(buf, "%d", objPtr->internalRep.indexValue); + else if (objPtr->internalRep.indexValue == -1) + len = sprintf(buf, "end"); + else { + len = sprintf(buf, "end%d", objPtr->internalRep.indexValue + 1); + } + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int idx, end = 0; + const char *str; + char *endptr; + + /* Get the string representation */ + str = Jim_String(objPtr); + + /* Try to convert into an index */ + if (strncmp(str, "end", 3) == 0) { + end = 1; + str += 3; + idx = 0; + } + else { + idx = strtol(str, &endptr, 10); + + if (endptr == str) { + goto badindex; + } + str = endptr; + } + + /* Now str may include or +<num> or -<num> */ + if (*str == '+' || *str == '-') { + int sign = (*str == '+' ? 1 : -1); + + idx += sign * strtol(++str, &endptr, 10); + if (str == endptr || *endptr) { + goto badindex; + } + str = endptr; + } + /* The only thing left should be spaces */ + while (isspace(UCHAR(*str))) { + str++; + } + if (*str) { + goto badindex; + } + if (end) { + if (idx > 0) { + idx = INT_MAX; + } + else { + /* end-1 is repesented as -2 */ + idx--; + } + } + else if (idx < 0) { + idx = -INT_MAX; + } + + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &indexObjType; + objPtr->internalRep.indexValue = idx; + return JIM_OK; + + badindex: + Jim_SetResultFormatted(interp, + "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr); + return JIM_ERR; +} + +int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) +{ + /* Avoid shimmering if the object is an integer. */ + if (objPtr->typePtr == &intObjType) { + jim_wide val = JimWideValue(objPtr); + + if (!(val < LONG_MIN) && !(val > LONG_MAX)) { + *indexPtr = (val < 0) ? -INT_MAX : (long)val;; + return JIM_OK; + } + } + if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *indexPtr = objPtr->internalRep.indexValue; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Return Code Object. + * ---------------------------------------------------------------------------*/ + +/* NOTE: These must be kept in the same order as JIM_OK, JIM_ERR, ... */ +static const char * const jimReturnCodes[] = { + [JIM_OK] = "ok", + [JIM_ERR] = "error", + [JIM_RETURN] = "return", + [JIM_BREAK] = "break", + [JIM_CONTINUE] = "continue", + [JIM_SIGNAL] = "signal", + [JIM_EXIT] = "exit", + [JIM_EVAL] = "eval", + NULL +}; + +#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) + +static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr); + +static const Jim_ObjType returnCodeObjType = { + "return-code", + NULL, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +/* Converts a (standard) return code to a string. Returns "?" for + * non-standard return codes. + */ +const char *Jim_ReturnCode(int code) +{ + if (code < 0 || code >= (int)jimReturnCodesSize) { + return "?"; + } + else { + return jimReturnCodes[code]; + } +} + +int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int returnCode; + jim_wide wideValue; + + /* Try to convert into an integer */ + if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) + returnCode = (int)wideValue; + else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &returnCodeObjType; + objPtr->internalRep.returnCode = returnCode; + return JIM_OK; +} + +int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr) +{ + if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *intPtr = objPtr->internalRep.returnCode; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Expression Parsing + * ---------------------------------------------------------------------------*/ +static int JimParseExprOperator(struct JimParserCtx *pc); +static int JimParseExprNumber(struct JimParserCtx *pc); +static int JimParseExprIrrational(struct JimParserCtx *pc); + +/* Exrp's Stack machine operators opcodes. */ + +/* Binary operators (numbers) */ +enum +{ + /* Continues on from the JIM_TT_ space */ + /* Operations */ + JIM_EXPROP_MUL = JIM_TT_EXPR_OP, /* 15 */ + JIM_EXPROP_DIV, + JIM_EXPROP_MOD, + JIM_EXPROP_SUB, + JIM_EXPROP_ADD, + JIM_EXPROP_LSHIFT, + JIM_EXPROP_RSHIFT, + JIM_EXPROP_ROTL, + JIM_EXPROP_ROTR, + JIM_EXPROP_LT, + JIM_EXPROP_GT, + JIM_EXPROP_LTE, + JIM_EXPROP_GTE, + JIM_EXPROP_NUMEQ, + JIM_EXPROP_NUMNE, + JIM_EXPROP_BITAND, /* 30 */ + JIM_EXPROP_BITXOR, + JIM_EXPROP_BITOR, + + /* Note must keep these together */ + JIM_EXPROP_LOGICAND, /* 33 */ + JIM_EXPROP_LOGICAND_LEFT, + JIM_EXPROP_LOGICAND_RIGHT, + + /* and these */ + JIM_EXPROP_LOGICOR, /* 36 */ + JIM_EXPROP_LOGICOR_LEFT, + JIM_EXPROP_LOGICOR_RIGHT, + + /* and these */ + /* Ternary operators */ + JIM_EXPROP_TERNARY, /* 39 */ + JIM_EXPROP_TERNARY_LEFT, + JIM_EXPROP_TERNARY_RIGHT, + + /* and these */ + JIM_EXPROP_COLON, /* 42 */ + JIM_EXPROP_COLON_LEFT, + JIM_EXPROP_COLON_RIGHT, + + JIM_EXPROP_POW, /* 45 */ + +/* Binary operators (strings) */ + JIM_EXPROP_STREQ, + JIM_EXPROP_STRNE, + JIM_EXPROP_STRIN, + JIM_EXPROP_STRNI, + +/* Unary operators (numbers) */ + JIM_EXPROP_NOT, + JIM_EXPROP_BITNOT, + JIM_EXPROP_UNARYMINUS, + JIM_EXPROP_UNARYPLUS, + + /* Functions */ + JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_ABS, + JIM_EXPROP_FUNC_DOUBLE, + JIM_EXPROP_FUNC_ROUND, + JIM_EXPROP_FUNC_RAND, + JIM_EXPROP_FUNC_SRAND, + + /* math functions from libm */ + JIM_EXPROP_FUNC_SIN, + JIM_EXPROP_FUNC_COS, + JIM_EXPROP_FUNC_TAN, + JIM_EXPROP_FUNC_ASIN, + JIM_EXPROP_FUNC_ACOS, + JIM_EXPROP_FUNC_ATAN, + JIM_EXPROP_FUNC_SINH, + JIM_EXPROP_FUNC_COSH, + JIM_EXPROP_FUNC_TANH, + JIM_EXPROP_FUNC_CEIL, + JIM_EXPROP_FUNC_FLOOR, + JIM_EXPROP_FUNC_EXP, + JIM_EXPROP_FUNC_LOG, + JIM_EXPROP_FUNC_LOG10, + JIM_EXPROP_FUNC_SQRT, + JIM_EXPROP_FUNC_POW, +}; + +struct JimExprState +{ + Jim_Obj **stack; + int stacklen; + int opcode; + int skip; +}; + +/* Operators table */ +typedef struct Jim_ExprOperator +{ + const char *name; + int precedence; + int arity; + int (*funcop) (Jim_Interp *interp, struct JimExprState * e); + int lazy; +} Jim_ExprOperator; + +static void ExprPush(struct JimExprState *e, Jim_Obj *obj) +{ + Jim_IncrRefCount(obj); + e->stack[e->stacklen++] = obj; +} + +static Jim_Obj *ExprPop(struct JimExprState *e) +{ + return e->stack[--e->stacklen]; +} + +static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 0; + int rc = JIM_OK; + Jim_Obj *A = ExprPop(e); + double dA, dC = 0; + jim_wide wA, wC = 0; + + if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + wC = wA; + break; + case JIM_EXPROP_FUNC_ROUND: + wC = wA; + break; + case JIM_EXPROP_FUNC_DOUBLE: + dC = wA; + intresult = 0; + break; + case JIM_EXPROP_FUNC_ABS: + wC = wA >= 0 ? wA : -wA; + break; + case JIM_EXPROP_UNARYMINUS: + wC = -wA; + break; + case JIM_EXPROP_UNARYPLUS: + wC = wA; + break; + case JIM_EXPROP_NOT: + wC = !wA; + break; + default: + abort(); + } + } + else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + wC = dA; + intresult = 1; + break; + case JIM_EXPROP_FUNC_ROUND: + wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); + intresult = 1; + break; + case JIM_EXPROP_FUNC_DOUBLE: + dC = dA; + break; + case JIM_EXPROP_FUNC_ABS: + dC = dA >= 0 ? dA : -dA; + break; + case JIM_EXPROP_UNARYMINUS: + dC = -dA; + break; + case JIM_EXPROP_UNARYPLUS: + dC = dA; + break; + case JIM_EXPROP_NOT: + wC = !dA; + intresult = 1; + break; + default: + abort(); + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static double JimRandDouble(Jim_Interp *interp) +{ + unsigned long x; + JimRandomBytes(interp, &x, sizeof(x)); + + return (double)x / (unsigned long)~0; +} + +static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + jim_wide wA; + + int rc = Jim_GetWide(interp, A, &wA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_BITNOT: + ExprPush(e, Jim_NewIntObj(interp, ~wA)); + break; + case JIM_EXPROP_FUNC_SRAND: + JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + break; + default: + abort(); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) +{ + JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); + + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + + return JIM_OK; +} + +#ifdef JIM_MATH_FUNCTIONS +static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int rc; + Jim_Obj *A = ExprPop(e); + double dA, dC; + + rc = Jim_GetDouble(interp, A, &dA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_SIN: + dC = sin(dA); + break; + case JIM_EXPROP_FUNC_COS: + dC = cos(dA); + break; + case JIM_EXPROP_FUNC_TAN: + dC = tan(dA); + break; + case JIM_EXPROP_FUNC_ASIN: + dC = asin(dA); + break; + case JIM_EXPROP_FUNC_ACOS: + dC = acos(dA); + break; + case JIM_EXPROP_FUNC_ATAN: + dC = atan(dA); + break; + case JIM_EXPROP_FUNC_SINH: + dC = sinh(dA); + break; + case JIM_EXPROP_FUNC_COSH: + dC = cosh(dA); + break; + case JIM_EXPROP_FUNC_TANH: + dC = tanh(dA); + break; + case JIM_EXPROP_FUNC_CEIL: + dC = ceil(dA); + break; + case JIM_EXPROP_FUNC_FLOOR: + dC = floor(dA); + break; + case JIM_EXPROP_FUNC_EXP: + dC = exp(dA); + break; + case JIM_EXPROP_FUNC_LOG: + dC = log(dA); + break; + case JIM_EXPROP_FUNC_LOG10: + dC = log10(dA); + break; + case JIM_EXPROP_FUNC_SQRT: + dC = sqrt(dA); + break; + default: + abort(); + } + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + + Jim_DecrRefCount(interp, A); + + return rc; +} +#endif + +/* A binary operation on two ints */ +static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + jim_wide wA, wB; + int rc = JIM_ERR; + + if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { + jim_wide wC; + + rc = JIM_OK; + + switch (e->opcode) { + case JIM_EXPROP_LSHIFT: + wC = wA << wB; + break; + case JIM_EXPROP_RSHIFT: + wC = wA >> wB; + break; + case JIM_EXPROP_BITAND: + wC = wA & wB; + break; + case JIM_EXPROP_BITXOR: + wC = wA ^ wB; + break; + case JIM_EXPROP_BITOR: + wC = wA | wB; + break; + case JIM_EXPROP_MOD: + if (wB == 0) { + wC = 0; + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + /* + * From Tcl 8.x + * + * This code is tricky: C doesn't guarantee much + * about the quotient or remainder, but Tcl does. + * The remainder always has the same sign as the + * divisor and a smaller absolute value. + */ + int negative = 0; + + if (wB < 0) { + wB = -wB; + wA = -wA; + negative = 1; + } + wC = wA % wB; + if (wC < 0) { + wC += wB; + } + if (negative) { + wC = -wC; + } + } + break; + case JIM_EXPROP_ROTL: + case JIM_EXPROP_ROTR:{ + /* uint32_t would be better. But not everyone has inttypes.h? */ + unsigned long uA = (unsigned long)wA; + unsigned long uB = (unsigned long)wB; + const unsigned int S = sizeof(unsigned long) * 8; + + /* Shift left by the word size or more is undefined. */ + uB %= S; + + if (e->opcode == JIM_EXPROP_ROTR) { + uB = S - uB; + } + wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); + break; + } + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + + +/* A binary operation on two ints or two doubles (or two strings for some ops) */ +static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 0; + int rc = JIM_OK; + double dA, dB, dC = 0; + jim_wide wA, wB, wC = 0; + + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + if ((A->typePtr != &doubleObjType || A->bytes) && + (B->typePtr != &doubleObjType || B->bytes) && + JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { + + /* Both are ints */ + + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: + wC = JimPowWide(wA, wB); + break; + case JIM_EXPROP_ADD: + wC = wA + wB; + break; + case JIM_EXPROP_SUB: + wC = wA - wB; + break; + case JIM_EXPROP_MUL: + wC = wA * wB; + break; + case JIM_EXPROP_DIV: + if (wB == 0) { + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + /* + * From Tcl 8.x + * + * This code is tricky: C doesn't guarantee much + * about the quotient or remainder, but Tcl does. + * The remainder always has the same sign as the + * divisor and a smaller absolute value. + */ + if (wB < 0) { + wB = -wB; + wA = -wA; + } + wC = wA / wB; + if (wA % wB < 0) { + wC--; + } + } + break; + case JIM_EXPROP_LT: + wC = wA < wB; + break; + case JIM_EXPROP_GT: + wC = wA > wB; + break; + case JIM_EXPROP_LTE: + wC = wA <= wB; + break; + case JIM_EXPROP_GTE: + wC = wA >= wB; + break; + case JIM_EXPROP_NUMEQ: + wC = wA == wB; + break; + case JIM_EXPROP_NUMNE: + wC = wA != wB; + break; + default: + abort(); + } + } + else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: +#ifdef JIM_MATH_FUNCTIONS + dC = pow(dA, dB); +#else + Jim_SetResultString(interp, "unsupported", -1); + rc = JIM_ERR; +#endif + break; + case JIM_EXPROP_ADD: + dC = dA + dB; + break; + case JIM_EXPROP_SUB: + dC = dA - dB; + break; + case JIM_EXPROP_MUL: + dC = dA * dB; + break; + case JIM_EXPROP_DIV: + if (dB == 0) { +#ifdef INFINITY + dC = dA < 0 ? -INFINITY : INFINITY; +#else + dC = (dA < 0 ? -1.0 : 1.0) * strtod("Inf", NULL); +#endif + } + else { + dC = dA / dB; + } + break; + case JIM_EXPROP_LT: + wC = dA < dB; + intresult = 1; + break; + case JIM_EXPROP_GT: + wC = dA > dB; + intresult = 1; + break; + case JIM_EXPROP_LTE: + wC = dA <= dB; + intresult = 1; + break; + case JIM_EXPROP_GTE: + wC = dA >= dB; + intresult = 1; + break; + case JIM_EXPROP_NUMEQ: + wC = dA == dB; + intresult = 1; + break; + case JIM_EXPROP_NUMNE: + wC = dA != dB; + intresult = 1; + break; + default: + abort(); + } + } + else { + /* Handle the string case */ + + /* REVISIT: Could optimise the eq/ne case by checking lengths */ + int i = Jim_StringCompareObj(interp, A, B, 0); + + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_LT: + wC = i < 0; + break; + case JIM_EXPROP_GT: + wC = i > 0; + break; + case JIM_EXPROP_LTE: + wC = i <= 0; + break; + case JIM_EXPROP_GTE: + wC = i >= 0; + break; + case JIM_EXPROP_NUMEQ: + wC = i == 0; + break; + case JIM_EXPROP_NUMNE: + wC = i != 0; + break; + default: + rc = JIM_ERR; + break; + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + +static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) +{ + int listlen; + int i; + + listlen = Jim_ListLength(interp, listObjPtr); + for (i = 0; i < listlen; i++) { + Jim_Obj *objPtr; + + Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); + + if (Jim_StringEqObj(objPtr, valObj)) { + return 1; + } + } + return 0; +} + +static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + jim_wide wC; + + switch (e->opcode) { + case JIM_EXPROP_STREQ: + case JIM_EXPROP_STRNE: { + int Alen, Blen; + const char *sA = Jim_GetString(A, &Alen); + const char *sB = Jim_GetString(B, &Blen); + + if (e->opcode == JIM_EXPROP_STREQ) { + wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0); + } + else { + wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0); + } + break; + } + case JIM_EXPROP_STRIN: + wC = JimSearchList(interp, B, A); + break; + case JIM_EXPROP_STRNI: + wC = !JimSearchList(interp, B, A); + break; + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return JIM_OK; +} + +static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) +{ + long l; + double d; + + if (Jim_GetLong(interp, obj, &l) == JIM_OK) { + return l != 0; + } + if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { + return d != 0; + } + return -1; +} + +static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + /* false, so skip RHS opcodes with a 0 result */ + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + /* true so continue */ + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + /* false, so do nothing */ + break; + + case 1: + /* true so skip RHS opcodes with a 1 result */ + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + /* Repush A */ + ExprPush(e, A); + + switch (ExprBool(interp, A)) { + case 0: + /* false, skip RHS opcodes */ + e->skip = JimWideValue(skip); + /* Push a dummy value */ + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + /* true so do nothing */ + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + /* No need to check for A as non-boolean */ + if (ExprBool(interp, A)) { + /* true, so skip RHS opcodes */ + e->skip = JimWideValue(skip); + /* Repush B as the answer */ + ExprPush(e, B); + } + + Jim_DecrRefCount(interp, skip); + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + return JIM_OK; +} + +static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) +{ + return JIM_OK; +} + +enum +{ + LAZY_NONE, + LAZY_OP, + LAZY_LEFT, + LAZY_RIGHT +}; + +/* name - precedence - arity - opcode */ +static const struct Jim_ExprOperator Jim_ExprOperators[] = { + [JIM_EXPROP_FUNC_INT] = {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_DOUBLE] = {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ABS] = {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ROUND] = {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_RAND] = {"rand", 400, 0, JimExprOpNone, LAZY_NONE}, + [JIM_EXPROP_FUNC_SRAND] = {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE}, + +#ifdef JIM_MATH_FUNCTIONS + [JIM_EXPROP_FUNC_SIN] = {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_COS] = {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_TAN] = {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ASIN] = {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ACOS] = {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ATAN] = {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_SINH] = {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_COSH] = {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_TANH] = {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_CEIL] = {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_FLOOR] = {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_EXP] = {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_LOG] = {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_LOG10] = {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_SQRT] = {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_POW] = {"pow", 400, 2, JimExprOpBin, LAZY_NONE}, +#endif + + [JIM_EXPROP_NOT] = {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_BITNOT] = {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE}, + [JIM_EXPROP_UNARYMINUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_UNARYPLUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, + + [JIM_EXPROP_POW] = {"**", 250, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_MUL] = {"*", 200, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_DIV] = {"/", 200, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_MOD] = {"%", 200, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_SUB] = {"-", 100, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_ADD] = {"+", 100, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_ROTL] = {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_ROTR] = {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_LSHIFT] = {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_RSHIFT] = {">>", 90, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_LT] = {"<", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_GT] = {">", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_LTE] = {"<=", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_GTE] = {">=", 80, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_NUMEQ] = {"==", 70, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_NUMNE] = {"!=", 70, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_STREQ] = {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE}, + [JIM_EXPROP_STRNE] = {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE}, + + [JIM_EXPROP_STRIN] = {"in", 55, 2, JimExprOpStrBin, LAZY_NONE}, + [JIM_EXPROP_STRNI] = {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE}, + + [JIM_EXPROP_BITAND] = {"&", 50, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_BITXOR] = {"^", 49, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_BITOR] = {"|", 48, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_LOGICAND] = {"&&", 10, 2, NULL, LAZY_OP}, + [JIM_EXPROP_LOGICOR] = {"||", 9, 2, NULL, LAZY_OP}, + + [JIM_EXPROP_TERNARY] = {"?", 5, 2, JimExprOpNull, LAZY_OP}, + [JIM_EXPROP_COLON] = {":", 5, 2, JimExprOpNull, LAZY_OP}, + + /* private operators */ + [JIM_EXPROP_TERNARY_LEFT] = {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT}, + [JIM_EXPROP_TERNARY_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, + [JIM_EXPROP_COLON_LEFT] = {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT}, + [JIM_EXPROP_COLON_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, + [JIM_EXPROP_LOGICAND_LEFT] = {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT}, + [JIM_EXPROP_LOGICAND_RIGHT] = {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT}, + [JIM_EXPROP_LOGICOR_LEFT] = {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT}, + [JIM_EXPROP_LOGICOR_RIGHT] = {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT}, +}; + +#define JIM_EXPR_OPERATORS_NUM \ + (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) + +static int JimParseExpression(struct JimParserCtx *pc) +{ + /* Discard spaces and quoted newline */ + while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + + if (pc->len == 0) { + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '(': + pc->tt = JIM_TT_SUBEXPR_START; + goto singlechar; + case ')': + pc->tt = JIM_TT_SUBEXPR_END; + goto singlechar; + case ',': + pc->tt = JIM_TT_SUBEXPR_COMMA; +singlechar: + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->p++; + pc->len--; + break; + case '[': + return JimParseCmd(pc); + case '$': + if (JimParseVar(pc) == JIM_ERR) + return JimParseExprOperator(pc); + else { + /* Don't allow expr sugar in expressions */ + if (pc->tt == JIM_TT_EXPRSUGAR) { + return JIM_ERR; + } + return JIM_OK; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + return JimParseExprNumber(pc); + case '"': + return JimParseQuote(pc); + case '{': + return JimParseBrace(pc); + + case 'N': + case 'I': + case 'n': + case 'i': + if (JimParseExprIrrational(pc) == JIM_ERR) + return JimParseExprOperator(pc); + break; + default: + return JimParseExprOperator(pc); + break; + } + return JIM_OK; +} + +static int JimParseExprNumber(struct JimParserCtx *pc) +{ + int allowdot = 1; + int allowhex = 0; + + /* Assume an integer for now */ + pc->tt = JIM_TT_EXPR_INT; + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (isdigit(UCHAR(*pc->p)) + || (allowhex && isxdigit(UCHAR(*pc->p))) + || (allowdot && *pc->p == '.') + || (pc->p - pc->tstart == 1 && *pc->tstart == '0' && (*pc->p == 'x' || *pc->p == 'X')) + ) { + if ((*pc->p == 'x') || (*pc->p == 'X')) { + allowhex = 1; + allowdot = 0; + } + if (*pc->p == '.') { + allowdot = 0; + pc->tt = JIM_TT_EXPR_DOUBLE; + } + pc->p++; + pc->len--; + if (!allowhex && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+' + || isdigit(UCHAR(pc->p[1])))) { + pc->p += 2; + pc->len -= 2; + pc->tt = JIM_TT_EXPR_DOUBLE; + } + } + pc->tend = pc->p - 1; + return JIM_OK; +} + +static int JimParseExprIrrational(struct JimParserCtx *pc) +{ + const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; + const char **token; + + for (token = Tokens; *token != NULL; token++) { + int len = strlen(*token); + + if (strncmp(*token, pc->p, len) == 0) { + pc->tstart = pc->p; + pc->tend = pc->p + len - 1; + pc->p += len; + pc->len -= len; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EXPR_DOUBLE; + return JIM_OK; + } + } + return JIM_ERR; +} + +static int JimParseExprOperator(struct JimParserCtx *pc) +{ + int i; + int bestIdx = -1, bestLen = 0; + + /* Try to get the longest match. */ + for (i = JIM_TT_EXPR_OP; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { + const char *opname; + int oplen; + + opname = Jim_ExprOperators[i].name; + if (opname == NULL) { + continue; + } + oplen = strlen(opname); + + if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) { + bestIdx = i; + bestLen = oplen; + } + } + if (bestIdx == -1) { + return JIM_ERR; + } + + /* Validate paretheses around function arguments */ + if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { + const char *p = pc->p + bestLen; + int len = pc->len - bestLen; + + while (len && isspace(UCHAR(*p))) { + len--; + p++; + } + if (*p != '(') { + return JIM_ERR; + } + } + pc->tstart = pc->p; + pc->tend = pc->p + bestLen - 1; + pc->p += bestLen; + pc->len -= bestLen; + pc->tline = pc->linenr; + + pc->tt = bestIdx; + return JIM_OK; +} + +static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) +{ + return &Jim_ExprOperators[opcode]; +} + +const char *jim_tt_name(int type) +{ + static const char * const tt_names[JIM_TT_EXPR_OP] = + { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", + "DBL", "$()" }; + if (type < JIM_TT_EXPR_OP) { + return tt_names[type]; + } + else { + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); + static char buf[20]; + + if (op && op->name) { + return op->name; + } + sprintf(buf, "(%d)", type); + return buf; + } +} + +/* ----------------------------------------------------------------------------- + * Expression Object + * ---------------------------------------------------------------------------*/ +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType exprObjType = { + "expression", + FreeExprInternalRep, + DupExprInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* Expr bytecode structure */ +typedef struct ExprByteCode +{ + int len; /* Length as number of tokens. */ + ScriptToken *token; /* Tokens array. */ + int inUse; /* Used for sharing. */ +} ExprByteCode; + +static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) +{ + int i; + + for (i = 0; i < expr->len; i++) { + Jim_DecrRefCount(interp, expr->token[i].objPtr); + } + Jim_Free(expr->token); + Jim_Free(expr); +} + +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ExprByteCode *expr = (void *)objPtr->internalRep.ptr; + + if (expr) { + if (--expr->inUse != 0) { + return; + } + + ExprFreeByteCode(interp, expr); + } +} + +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + /* Just returns an simple string. */ + dupPtr->typePtr = NULL; +} + +/* Check if an expr program looks correct. */ +static int ExprCheckCorrectness(ExprByteCode * expr) +{ + int i; + int stacklen = 0; + int ternary = 0; + + /* Try to check if there are stack underflows, + * and make sure at the end of the program there is + * a single result on the stack. */ + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op) { + stacklen -= op->arity; + if (stacklen < 0) { + break; + } + if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { + ternary++; + } + else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { + ternary--; + } + } + + /* All operations and operands add one to the stack */ + stacklen++; + } + if (stacklen != 1 || ternary != 0) { + return JIM_ERR; + } + return JIM_OK; +} + +/* This procedure converts every occurrence of || and && opereators + * in lazy unary versions. + * + * a b || is converted into: + * + * a <offset> |L b |R + * + * a b && is converted into: + * + * a <offset> &L b &R + * + * "|L" checks if 'a' is true: + * 1) if it is true pushes 1 and skips <offset> instructions to reach + * the opcode just after |R. + * 2) if it is false does nothing. + * "|R" checks if 'b' is true: + * 1) if it is true pushes 1, otherwise pushes 0. + * + * "&L" checks if 'a' is true: + * 1) if it is true does nothing. + * 2) If it is false pushes 0 and skips <offset> instructions to reach + * the opcode just after &R + * "&R" checks if 'a' is true: + * if it is true pushes 1, otherwise pushes 0. + */ +static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + int i; + + int leftindex, arity, offset; + + /* Search for the end of the first operator */ + leftindex = expr->len - 1; + + arity = 1; + while (arity) { + ScriptToken *tt = &expr->token[leftindex]; + + if (tt->type >= JIM_TT_EXPR_OP) { + arity += JimExprOperatorInfoByOpcode(tt->type)->arity; + } + arity--; + if (--leftindex < 0) { + return JIM_ERR; + } + } + leftindex++; + + /* Move them up */ + memmove(&expr->token[leftindex + 2], &expr->token[leftindex], + sizeof(*expr->token) * (expr->len - leftindex)); + expr->len += 2; + offset = (expr->len - leftindex) - 1; + + /* Now we rely on the fact the the left and right version have opcodes + * 1 and 2 after the main opcode respectively + */ + expr->token[leftindex + 1].type = t->type + 1; + expr->token[leftindex + 1].objPtr = interp->emptyObj; + + expr->token[leftindex].type = JIM_TT_EXPR_INT; + expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); + + /* Now add the 'R' operator */ + expr->token[expr->len].objPtr = interp->emptyObj; + expr->token[expr->len].type = t->type + 2; + expr->len++; + + /* Do we need to adjust the skip count for any &L, |L, ?L or :L in the left operand? */ + for (i = leftindex - 1; i > 0; i--) { + if (JimExprOperatorInfoByOpcode(expr->token[i].type)->lazy == LAZY_LEFT) { + if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { + JimWideValue(expr->token[i - 1].objPtr) += 2; + } + } + } + return JIM_OK; +} + +static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + struct ScriptToken *token = &expr->token[expr->len]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op->lazy == LAZY_OP) { + if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { + Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); + return JIM_ERR; + } + } + else { + token->objPtr = interp->emptyObj; + token->type = t->type; + expr->len++; + } + return JIM_OK; +} + +/** + * Returns the index of the COLON_LEFT to the left of 'right_index' + * taking into account nesting. + * + * The expression *must* be well formed, thus a COLON_LEFT will always be found. + */ +static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) +{ + int ternary_count = 1; + + right_index--; + + while (right_index > 1) { + if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { + ternary_count--; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { + ternary_count++; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { + return right_index; + } + right_index--; + } + + /*notreached*/ + return -1; +} + +/** + * Find the left/right indices for the ternary expression to the left of 'right_index'. + * + * Returns 1 if found, and fills in *prev_right_index and *prev_left_index. + * Otherwise returns 0. + */ +static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) +{ + int i = right_index - 1; + int ternary_count = 1; + + while (i > 1) { + if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { + if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { + *prev_right_index = i - 2; + *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); + return 1; + } + } + else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { + if (ternary_count == 0) { + return 0; + } + ternary_count++; + } + i--; + } + return 0; +} + +/* +* ExprTernaryReorderExpression description +* ======================================== +* +* ?: is right-to-left associative which doesn't work with the stack-based +* expression engine. The fix is to reorder the bytecode. +* +* The expression: +* +* expr 1?2:0?3:4 +* +* Has initial bytecode: +* +* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '0' (44=COLON_RIGHT) +* '2' (40=TERNARY_LEFT) '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) +* +* The fix involves simulating this expression instead: +* +* expr 1?2:(0?3:4) +* +* With the following bytecode: +* +* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '10' (43=COLON_LEFT) '0' '2' (40=TERNARY_LEFT) +* '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) (44=COLON_RIGHT) +* +* i.e. The token COLON_RIGHT at index 8 is moved towards the end of the stack, all tokens above 8 +* are shifted down and the skip count of the token JIM_EXPROP_COLON_LEFT at index 5 is +* incremented by the amount tokens shifted down. The token JIM_EXPROP_COLON_RIGHT that is moved +* is identified as immediately preceeding a token JIM_EXPROP_TERNARY_LEFT +* +* ExprTernaryReorderExpression works thus as follows : +* - start from the end of the stack +* - while walking towards the beginning of the stack +* if token=JIM_EXPROP_COLON_RIGHT then +* find the associated token JIM_EXPROP_TERNARY_LEFT, which allows to +* find the associated token previous(JIM_EXPROP_COLON_RIGHT) +* find the associated token previous(JIM_EXPROP_LEFT_RIGHT) +* if all found then +* perform the rotation +* update the skip count of the token previous(JIM_EXPROP_LEFT_RIGHT) +* end if +* end if +* +* Note: care has to be taken for nested ternary constructs!!! +*/ +static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) +{ + int i; + + for (i = expr->len - 1; i > 1; i--) { + int prev_right_index; + int prev_left_index; + int j; + ScriptToken tmp; + + if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { + continue; + } + + /* COLON_RIGHT found: get the indexes needed to move the tokens in the stack (if any) */ + if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { + continue; + } + + /* + ** rotate tokens down + ** + ** +-> [i] : JIM_EXPROP_COLON_RIGHT + ** | | | + ** | V V + ** | [...] : ... + ** | | | + ** | V V + ** | [...] : ... + ** | | | + ** | V V + ** +- [prev_right_index] : JIM_EXPROP_COLON_RIGHT + */ + tmp = expr->token[prev_right_index]; + for (j = prev_right_index; j < i; j++) { + expr->token[j] = expr->token[j + 1]; + } + expr->token[i] = tmp; + + /* Increment the 'skip' count associated to the previous JIM_EXPROP_COLON_LEFT token + * + * This is 'colon left increment' = i - prev_right_index + * + * [prev_left_index] : JIM_EXPROP_LEFT_RIGHT + * [prev_left_index-1] : skip_count + * + */ + JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); + + /* Adjust for i-- in the loop */ + i++; + } +} + +static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) +{ + Jim_Stack stack; + ExprByteCode *expr; + int ok = 1; + int i; + int prevtt = JIM_TT_NONE; + int have_ternary = 0; + + /* -1 for EOL */ + int count = tokenlist->count - 1; + + expr = Jim_Alloc(sizeof(*expr)); + expr->inUse = 1; + expr->len = 0; + + Jim_InitStack(&stack); + + /* Need extra bytecodes for lazy operators. + * Also check for the ternary operator + */ + for (i = 0; i < tokenlist->count; i++) { + ParseToken *t = &tokenlist->list[i]; + + if (JimExprOperatorInfoByOpcode(t->type)->lazy == LAZY_OP) { + count += 2; + /* Ternary is a lazy op but also needs reordering */ + if (t->type == JIM_EXPROP_TERNARY) { + have_ternary = 1; + } + } + } + + expr->token = Jim_Alloc(sizeof(ScriptToken) * count); + + for (i = 0; i < tokenlist->count && ok; i++) { + ParseToken *t = &tokenlist->list[i]; + + /* Next token will be stored here */ + struct ScriptToken *token = &expr->token[expr->len]; + + if (t->type == JIM_TT_EOL) { + break; + } + + switch (t->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + case JIM_TT_VAR: + case JIM_TT_DICTSUGAR: + case JIM_TT_EXPRSUGAR: + case JIM_TT_CMD: + token->objPtr = Jim_NewStringObj(interp, t->token, t->len); + token->type = t->type; + if (t->type == JIM_TT_CMD) { + /* Only commands need source info */ + JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); + } + expr->len++; + break; + + case JIM_TT_EXPR_INT: + token->objPtr = Jim_NewIntObj(interp, strtoull(t->token, NULL, 0)); + token->type = t->type; + expr->len++; + break; + + case JIM_TT_EXPR_DOUBLE: + token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, NULL)); + token->type = t->type; + expr->len++; + break; + + case JIM_TT_SUBEXPR_START: + Jim_StackPush(&stack, t); + prevtt = JIM_TT_NONE; + continue; + + case JIM_TT_SUBEXPR_COMMA: + /* Simple approach. Comma is simply ignored */ + continue; + + case JIM_TT_SUBEXPR_END: + ok = 0; + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 1; + break; + } + + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + goto err; + } + } + if (!ok) { + Jim_SetResultString(interp, "Unexpected close parenthesis", -1); + goto err; + } + break; + + + default:{ + /* Must be an operator */ + const struct Jim_ExprOperator *op; + ParseToken *tt; + + /* Convert -/+ to unary minus or unary plus if necessary */ + if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { + if (t->type == JIM_EXPROP_SUB) { + t->type = JIM_EXPROP_UNARYMINUS; + } + else if (t->type == JIM_EXPROP_ADD) { + t->type = JIM_EXPROP_UNARYPLUS; + } + } + + op = JimExprOperatorInfoByOpcode(t->type); + + /* Now handle precedence */ + while ((tt = Jim_StackPeek(&stack)) != NULL) { + const struct Jim_ExprOperator *tt_op = + JimExprOperatorInfoByOpcode(tt->type); + + /* Note that right-to-left associativity of ?: operator is handled later */ + + if (op->arity != 1 && tt_op->precedence >= op->precedence) { + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + Jim_StackPop(&stack); + } + else { + break; + } + } + Jim_StackPush(&stack, t); + break; + } + } + prevtt = t->type; + } + + /* Reduce any remaining subexpr */ + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 0; + Jim_SetResultString(interp, "Missing close parenthesis", -1); + goto err; + } + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + } + + if (have_ternary) { + ExprTernaryReorderExpression(interp, expr); + } + + err: + /* Free the stack used for the compilation. */ + Jim_FreeStack(&stack); + + for (i = 0; i < expr->len; i++) { + Jim_IncrRefCount(expr->token[i].objPtr); + } + + if (!ok) { + ExprFreeByteCode(interp, expr); + return NULL; + } + + return expr; +} + + +/* This method takes the string representation of an expression + * and generates a program for the Expr's stack-based VM. */ +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int exprTextLen; + const char *exprText; + struct JimParserCtx parser; + struct ExprByteCode *expr; + ParseTokenList tokenlist; + int line; + Jim_Obj *fileNameObj; + int rc = JIM_ERR; + + /* Try to get information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + line = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + Jim_IncrRefCount(fileNameObj); + + exprText = Jim_GetString(objPtr, &exprTextLen); + + /* Initially tokenise the expression into tokenlist */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, exprText, exprTextLen, line); + while (!parser.eof) { + if (JimParseExpression(&parser) != JIM_OK) { + ScriptTokenListFree(&tokenlist); + invalidexpr: + Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); + expr = NULL; + goto err; + } + + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + +#ifdef DEBUG_SHOW_EXPR_TOKENS + { + int i; + printf("==== Expr Tokens ====\n"); + for (i = 0; i < tokenlist.count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), + tokenlist.list[i].len, tokenlist.list[i].token); + } + } +#endif + + /* Now create the expression bytecode from the tokenlist */ + expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + + if (!expr) { + goto err; + } + +#ifdef DEBUG_SHOW_EXPR + { + int i; + + printf("==== Expr ====\n"); + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + + printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } + } +#endif + + /* Check program correctness. */ + if (ExprCheckCorrectness(expr) != JIM_OK) { + ExprFreeByteCode(interp, expr); + goto invalidexpr; + } + + rc = JIM_OK; + + err: + /* Free the old internal rep and set the new one. */ + Jim_DecrRefCount(interp, fileNameObj); + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, expr); + objPtr->typePtr = &exprObjType; + return rc; +} + +static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &exprObjType) { + if (SetExprFromAny(interp, objPtr) != JIM_OK) { + return NULL; + } + } + return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); +} + +/* ----------------------------------------------------------------------------- + * Expressions evaluation. + * Jim uses a specialized stack-based virtual machine for expressions, + * that takes advantage of the fact that expr's operators + * can't be redefined. + * + * Jim_EvalExpression() uses the bytecode compiled by + * SetExprFromAny() method of the "expression" object. + * + * On success a Tcl Object containing the result of the evaluation + * is stored into expResultPtrPtr (having refcount of 1), and JIM_OK is + * returned. + * On error the function returns a retcode != to JIM_OK and set a suitable + * error on the interp. + * ---------------------------------------------------------------------------*/ +#define JIM_EE_STATICSTACK_LEN 10 + +int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) +{ + ExprByteCode *expr; + Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; + int i; + int retcode = JIM_OK; + struct JimExprState e; + + expr = JimGetExpression(interp, exprObjPtr); + if (!expr) { + return JIM_ERR; /* error in expression. */ + } + +#ifdef JIM_OPTIMIZATION + /* Check for one of the following common expressions used by while/for + * + * CONST + * $a + * !$a + * $a < CONST, $a < $b + * $a <= CONST, $a <= $b + * $a > CONST, $a > $b + * $a >= CONST, $a >= $b + * $a != CONST, $a != $b + * $a == CONST, $a == $b + */ + { + Jim_Obj *objPtr; + + /* STEP 1 -- Check if there are the conditions to run the specialized + * version of while */ + + switch (expr->len) { + case 1: + if (expr->token[0].type == JIM_TT_EXPR_INT) { + *exprResultPtrPtr = expr->token[0].objPtr; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + if (expr->token[0].type == JIM_TT_VAR) { + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG); + if (objPtr) { + *exprResultPtrPtr = objPtr; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + + case 2: + if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) { + jim_wide wideValue; + + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) { + *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + + case 3: + if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT + || expr->token[1].type == JIM_TT_VAR)) { + switch (expr->token[2].type) { + case JIM_EXPROP_LT: + case JIM_EXPROP_LTE: + case JIM_EXPROP_GT: + case JIM_EXPROP_GTE: + case JIM_EXPROP_NUMEQ: + case JIM_EXPROP_NUMNE:{ + /* optimise ok */ + jim_wide wideValueA; + jim_wide wideValueB; + + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) { + if (expr->token[1].type == JIM_TT_VAR) { + objPtr = + Jim_GetVariable(interp, expr->token[1].objPtr, + JIM_NONE); + } + else { + objPtr = expr->token[1].objPtr; + } + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) { + int cmpRes; + + switch (expr->token[2].type) { + case JIM_EXPROP_LT: + cmpRes = wideValueA < wideValueB; + break; + case JIM_EXPROP_LTE: + cmpRes = wideValueA <= wideValueB; + break; + case JIM_EXPROP_GT: + cmpRes = wideValueA > wideValueB; + break; + case JIM_EXPROP_GTE: + cmpRes = wideValueA >= wideValueB; + break; + case JIM_EXPROP_NUMEQ: + cmpRes = wideValueA == wideValueB; + break; + case JIM_EXPROP_NUMNE: + cmpRes = wideValueA != wideValueB; + break; + default: /*notreached */ + cmpRes = 0; + } + *exprResultPtrPtr = + cmpRes ? interp->trueObj : interp->falseObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + } + } + } + break; + } + } +#endif + + /* In order to avoid that the internal repr gets freed due to + * shimmering of the exprObjPtr's object, we make the internal rep + * shared. */ + expr->inUse++; + + /* The stack-based expr VM itself */ + + /* Stack allocation. Expr programs have the feature that + * a program of length N can't require a stack longer than + * N. */ + if (expr->len > JIM_EE_STATICSTACK_LEN) + e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); + else + e.stack = staticStack; + + e.stacklen = 0; + + /* Execute every instruction */ + for (i = 0; i < expr->len && retcode == JIM_OK; i++) { + Jim_Obj *objPtr; + + switch (expr->token[i].type) { + case JIM_TT_EXPR_INT: + case JIM_TT_EXPR_DOUBLE: + case JIM_TT_STR: + ExprPush(&e, expr->token[i].objPtr); + break; + + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_ESC: + retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); + if (retcode == JIM_OK) { + ExprPush(&e, objPtr); + } + break; + + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, expr->token[i].objPtr); + if (retcode == JIM_OK) { + ExprPush(&e, Jim_GetResult(interp)); + } + break; + + default:{ + /* Find and execute the operation */ + e.skip = 0; + e.opcode = expr->token[i].type; + + retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); + /* Skip some opcodes if necessary */ + i += e.skip; + continue; + } + } + } + + expr->inUse--; + + if (retcode == JIM_OK) { + *exprResultPtrPtr = ExprPop(&e); + } + else { + for (i = 0; i < e.stacklen; i++) { + Jim_DecrRefCount(interp, e.stack[i]); + } + } + if (e.stack != staticStack) { + Jim_Free(e.stack); + } + return retcode; +} + +int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) +{ + int retcode; + jim_wide wideValue; + double doubleValue; + Jim_Obj *exprResultPtr; + + retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); + if (retcode != JIM_OK) + return retcode; + + if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_ERR; + } + else { + Jim_DecrRefCount(interp, exprResultPtr); + *boolPtr = doubleValue != 0; + return JIM_OK; + } + } + *boolPtr = wideValue != 0; + + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * ScanFormat String Object + * ---------------------------------------------------------------------------*/ + +/* This Jim_Obj will held a parsed representation of a format string passed to + * the Jim_ScanString command. For error diagnostics, the scanformat string has + * to be parsed in its entirely first and then, if correct, can be used for + * scanning. To avoid endless re-parsing, the parsed representation will be + * stored in an internal representation and re-used for performance reason. */ + +/* A ScanFmtPartDescr will held the information of /one/ part of the whole + * scanformat string. This part will later be used to extract information + * out from the string to be parsed by Jim_ScanString */ + +typedef struct ScanFmtPartDescr +{ + char type; /* Type of conversion (e.g. c, d, f) */ + char modifier; /* Modify type (e.g. l - long, h - short */ + size_t width; /* Maximal width of input to be converted */ + int pos; /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */ + char *arg; /* Specification of a CHARSET conversion */ + char *prefix; /* Prefix to be scanned literally before conversion */ +} ScanFmtPartDescr; + +/* The ScanFmtStringObj will hold the internal representation of a scanformat + * string parsed and separated in part descriptions. Furthermore it contains + * the original string representation of the scanformat string to allow for + * fast update of the Jim_Obj's string representation part. + * + * As an add-on the internal object representation adds some scratch pad area + * for usage by Jim_ScanString to avoid endless allocating and freeing of + * memory for purpose of string scanning. + * + * The error member points to a static allocated string in case of a mal- + * formed scanformat string or it contains '0' (NULL) in case of a valid + * parse representation. + * + * The whole memory of the internal representation is allocated as a single + * area of memory that will be internally separated. So freeing and duplicating + * of such an object is cheap */ + +typedef struct ScanFmtStringObj +{ + jim_wide size; /* Size of internal repr in bytes */ + char *stringRep; /* Original string representation */ + size_t count; /* Number of ScanFmtPartDescr contained */ + size_t convCount; /* Number of conversions that will assign */ + size_t maxPos; /* Max position index if XPG3 is used */ + const char *error; /* Ptr to error text (NULL if no error */ + char *scratch; /* Some scratch pad used by Jim_ScanString */ + ScanFmtPartDescr descr[1]; /* The vector of partial descriptions */ +} ScanFmtStringObj; + + +static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfScanFmt(Jim_Obj *objPtr); + +static const Jim_ObjType scanFmtStringObjType = { + "scanformatstring", + FreeScanFmtInternalRep, + DupScanFmtInternalRep, + UpdateStringOfScanFmt, + JIM_TYPE_NONE, +}; + +void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + Jim_Free((char *)objPtr->internalRep.ptr); + objPtr->internalRep.ptr = 0; +} + +void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + size_t size = (size_t) ((ScanFmtStringObj *) srcPtr->internalRep.ptr)->size; + ScanFmtStringObj *newVec = (ScanFmtStringObj *) Jim_Alloc(size); + + JIM_NOTUSED(interp); + memcpy(newVec, srcPtr->internalRep.ptr, size); + dupPtr->internalRep.ptr = newVec; + dupPtr->typePtr = &scanFmtStringObjType; +} + +void UpdateStringOfScanFmt(Jim_Obj *objPtr) +{ + char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep; + + objPtr->bytes = Jim_StrDup(bytes); + objPtr->length = strlen(bytes); +} + +/* SetScanFmtFromAny will parse a given string and create the internal + * representation of the format specification. In case of an error + * the error data member of the internal representation will be set + * to an descriptive error text and the function will be left with + * JIM_ERR to indicate unsucessful parsing (aka. malformed scanformat + * specification */ + +static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ScanFmtStringObj *fmtObj; + char *buffer; + int maxCount, i, approxSize, lastPos = -1; + const char *fmt = objPtr->bytes; + int maxFmtLen = objPtr->length; + const char *fmtEnd = fmt + maxFmtLen; + int curr; + + Jim_FreeIntRep(interp, objPtr); + /* Count how many conversions could take place maximally */ + for (i = 0, maxCount = 0; i < maxFmtLen; ++i) + if (fmt[i] == '%') + ++maxCount; + /* Calculate an approximation of the memory necessary */ + approxSize = sizeof(ScanFmtStringObj) /* Size of the container */ + +(maxCount + 1) * sizeof(ScanFmtPartDescr) /* Size of all partials */ + +maxFmtLen * sizeof(char) + 3 + 1 /* Scratch + "%n" + '\0' */ + + maxFmtLen * sizeof(char) + 1 /* Original stringrep */ + + maxFmtLen * sizeof(char) /* Arg for CHARSETs */ + +(maxCount + 1) * sizeof(char) /* '\0' for every partial */ + +1; /* safety byte */ + fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); + memset(fmtObj, 0, approxSize); + fmtObj->size = approxSize; + fmtObj->maxPos = 0; + fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; + fmtObj->stringRep = fmtObj->scratch + maxFmtLen + 3 + 1; + memcpy(fmtObj->stringRep, fmt, maxFmtLen); + buffer = fmtObj->stringRep + maxFmtLen + 1; + objPtr->internalRep.ptr = fmtObj; + objPtr->typePtr = &scanFmtStringObjType; + for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { + int width = 0, skip; + ScanFmtPartDescr *descr = &fmtObj->descr[curr]; + + fmtObj->count++; + descr->width = 0; /* Assume width unspecified */ + /* Overread and store any "literal" prefix */ + if (*fmt != '%' || fmt[1] == '%') { + descr->type = 0; + descr->prefix = &buffer[i]; + for (; fmt < fmtEnd; ++fmt) { + if (*fmt == '%') { + if (fmt[1] != '%') + break; + ++fmt; + } + buffer[i++] = *fmt; + } + buffer[i++] = 0; + } + /* Skip the conversion introducing '%' sign */ + ++fmt; + /* End reached due to non-conversion literal only? */ + if (fmt >= fmtEnd) + goto done; + descr->pos = 0; /* Assume "natural" positioning */ + if (*fmt == '*') { + descr->pos = -1; /* Okay, conversion will not be assigned */ + ++fmt; + } + else + fmtObj->convCount++; /* Otherwise count as assign-conversion */ + /* Check if next token is a number (could be width or pos */ + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + fmt += skip; + /* Was the number a XPG3 position specifier? */ + if (descr->pos != -1 && *fmt == '$') { + int prev; + + ++fmt; + descr->pos = width; + width = 0; + /* Look if "natural" postioning and XPG3 one was mixed */ + if ((lastPos == 0 && descr->pos > 0) + || (lastPos > 0 && descr->pos == 0)) { + fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; + return JIM_ERR; + } + /* Look if this position was already used */ + for (prev = 0; prev < curr; ++prev) { + if (fmtObj->descr[prev].pos == -1) + continue; + if (fmtObj->descr[prev].pos == descr->pos) { + fmtObj->error = + "variable is assigned by multiple \"%n$\" conversion specifiers"; + return JIM_ERR; + } + } + /* Try to find a width after the XPG3 specifier */ + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + descr->width = width; + fmt += skip; + } + if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) + fmtObj->maxPos = descr->pos; + } + else { + /* Number was not a XPG3, so it has to be a width */ + descr->width = width; + } + } + /* If positioning mode was undetermined yet, fix this */ + if (lastPos == -1) + lastPos = descr->pos; + /* Handle CHARSET conversion type ... */ + if (*fmt == '[') { + int swapped = 1, beg = i, end, j; + + descr->type = '['; + descr->arg = &buffer[i]; + ++fmt; + if (*fmt == '^') + buffer[i++] = *fmt++; + if (*fmt == ']') + buffer[i++] = *fmt++; + while (*fmt && *fmt != ']') + buffer[i++] = *fmt++; + if (*fmt != ']') { + fmtObj->error = "unmatched [ in format string"; + return JIM_ERR; + } + end = i; + buffer[i++] = 0; + /* In case a range fence was given "backwards", swap it */ + while (swapped) { + swapped = 0; + for (j = beg + 1; j < end - 1; ++j) { + if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { + char tmp = buffer[j - 1]; + + buffer[j - 1] = buffer[j + 1]; + buffer[j + 1] = tmp; + swapped = 1; + } + } + } + } + else { + /* Remember any valid modifier if given */ + if (strchr("hlL", *fmt) != 0) + descr->modifier = tolower((int)*fmt++); + + descr->type = *fmt; + if (strchr("efgcsndoxui", *fmt) == 0) { + fmtObj->error = "bad scan conversion character"; + return JIM_ERR; + } + else if (*fmt == 'c' && descr->width != 0) { + fmtObj->error = "field width may not be specified in %c " "conversion"; + return JIM_ERR; + } + else if (*fmt == 'u' && descr->modifier == 'l') { + fmtObj->error = "unsigned wide not supported"; + return JIM_ERR; + } + } + curr++; + } + done: + return JIM_OK; +} + +/* Some accessor macros to allow lowlevel access to fields of internal repr */ + +#define FormatGetCnvCount(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount +#define FormatGetMaxPos(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->maxPos +#define FormatGetError(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error + +/* JimScanAString is used to scan an unspecified string that ends with + * next WS, or a string that is specified via a charset. + * + */ +static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str) +{ + char *buffer = Jim_StrDup(str); + char *p = buffer; + + while (*str) { + int c; + int n; + + if (!sdescr && isspace(UCHAR(*str))) + break; /* EOS via WS if unspecified */ + + n = utf8_tounicode(str, &c); + if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) + break; + while (n--) + *p++ = *str++; + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer); +} + +/* ScanOneEntry will scan one entry out of the string passed as argument. + * It use the sscanf() function for this task. After extracting and + * converting of the value, the count of scanned characters will be + * returned of -1 in case of no conversion tool place and string was + * already scanned thru */ + +static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen, + ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr) +{ + const char *tok; + const ScanFmtPartDescr *descr = &fmtObj->descr[idx]; + size_t scanned = 0; + size_t anchor = pos; + int i; + Jim_Obj *tmpObj = NULL; + + /* First pessimistically assume, we will not scan anything :-) */ + *valObjPtr = 0; + if (descr->prefix) { + /* There was a prefix given before the conversion, skip it and adjust + * the string-to-be-parsed accordingly */ + /* XXX: Should be checking strLen, not str[pos] */ + for (i = 0; pos < strLen && descr->prefix[i]; ++i) { + /* If prefix require, skip WS */ + if (isspace(UCHAR(descr->prefix[i]))) + while (pos < strLen && isspace(UCHAR(str[pos]))) + ++pos; + else if (descr->prefix[i] != str[pos]) + break; /* Prefix do not match here, leave the loop */ + else + ++pos; /* Prefix matched so far, next round */ + } + if (pos >= strLen) { + return -1; /* All of str consumed: EOF condition */ + } + else if (descr->prefix[i] != 0) + return 0; /* Not whole prefix consumed, no conversion possible */ + } + /* For all but following conversion, skip leading WS */ + if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') + while (isspace(UCHAR(str[pos]))) + ++pos; + /* Determine how much skipped/scanned so far */ + scanned = pos - anchor; + + /* %c is a special, simple case. no width */ + if (descr->type == 'n') { + /* Return pseudo conversion means: how much scanned so far? */ + *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); + } + else if (pos >= strLen) { + /* Cannot scan anything, as str is totally consumed */ + return -1; + } + else if (descr->type == 'c') { + int c; + scanned += utf8_tounicode(&str[pos], &c); + *valObjPtr = Jim_NewIntObj(interp, c); + return scanned; + } + else { + /* Processing of conversions follows ... */ + if (descr->width > 0) { + /* Do not try to scan as fas as possible but only the given width. + * To ensure this, we copy the part that should be scanned. */ + size_t sLen = utf8_strlen(&str[pos], strLen - pos); + size_t tLen = descr->width > sLen ? sLen : descr->width; + + tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); + tok = tmpObj->bytes; + } + else { + /* As no width was given, simply refer to the original string */ + tok = &str[pos]; + } + switch (descr->type) { + case 'd': + case 'o': + case 'x': + case 'u': + case 'i':{ + char *endp; /* Position where the number finished */ + jim_wide w; + + int base = descr->type == 'o' ? 8 + : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; + + /* Try to scan a number with the given base */ + w = strtoull(tok, &endp, base); + if (endp == tok && base == 0) { + /* If scanning failed, and base was undetermined, simply + * put it to 10 and try once more. This should catch the + * case where %i begin to parse a number prefix (e.g. + * '0x' but no further digits follows. This will be + * handled as a ZERO followed by a char 'x' by Tcl */ + w = strtoull(tok, &endp, 10); + } + + if (endp != tok) { + /* There was some number sucessfully scanned! */ + *valObjPtr = Jim_NewIntObj(interp, w); + + /* Adjust the number-of-chars scanned so far */ + scanned += endp - tok; + } + else { + /* Nothing was scanned. We have to determine if this + * happened due to e.g. prefix mismatch or input str + * exhausted */ + scanned = *tok ? 0 : -1; + } + break; + } + case 's': + case '[':{ + *valObjPtr = JimScanAString(interp, descr->arg, tok); + scanned += Jim_Length(*valObjPtr); + break; + } + case 'e': + case 'f': + case 'g':{ + char *endp; + double value = strtod(tok, &endp); + + if (endp != tok) { + /* There was some number sucessfully scanned! */ + *valObjPtr = Jim_NewDoubleObj(interp, value); + /* Adjust the number-of-chars scanned so far */ + scanned += endp - tok; + } + else { + /* Nothing was scanned. We have to determine if this + * happened due to e.g. prefix mismatch or input str + * exhausted */ + scanned = *tok ? 0 : -1; + } + break; + } + } + /* If a substring was allocated (due to pre-defined width) do not + * forget to free it */ + if (tmpObj) { + Jim_FreeNewObj(interp, tmpObj); + } + } + return scanned; +} + +/* Jim_ScanString is the workhorse of string scanning. It will scan a given + * string and returns all converted (and not ignored) values in a list back + * to the caller. If an error occured, a NULL pointer will be returned */ + +Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags) +{ + size_t i, pos; + int scanned = 1; + const char *str = Jim_String(strObjPtr); + int strLen = Jim_Utf8Length(interp, strObjPtr); + Jim_Obj *resultList = 0; + Jim_Obj **resultVec = 0; + int resultc; + Jim_Obj *emptyStr = 0; + ScanFmtStringObj *fmtObj; + + /* This should never happen. The format object should already be of the correct type */ + JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); + + fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; + /* Check if format specification was valid */ + if (fmtObj->error != 0) { + if (flags & JIM_ERRMSG) + Jim_SetResultString(interp, fmtObj->error, -1); + return 0; + } + /* Allocate a new "shared" empty string for all unassigned conversions */ + emptyStr = Jim_NewEmptyStringObj(interp); + Jim_IncrRefCount(emptyStr); + /* Create a list and fill it with empty strings up to max specified XPG3 */ + resultList = Jim_NewListObj(interp, 0, 0); + if (fmtObj->maxPos > 0) { + for (i = 0; i < fmtObj->maxPos; ++i) + Jim_ListAppendElement(interp, resultList, emptyStr); + JimListGetElements(interp, resultList, &resultc, &resultVec); + } + /* Now handle every partial format description */ + for (i = 0, pos = 0; i < fmtObj->count; ++i) { + ScanFmtPartDescr *descr = &(fmtObj->descr[i]); + Jim_Obj *value = 0; + + /* Only last type may be "literal" w/o conversion - skip it! */ + if (descr->type == 0) + continue; + /* As long as any conversion could be done, we will proceed */ + if (scanned > 0) + scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); + /* In case our first try results in EOF, we will leave */ + if (scanned == -1 && i == 0) + goto eof; + /* Advance next pos-to-be-scanned for the amount scanned already */ + pos += scanned; + + /* value == 0 means no conversion took place so take empty string */ + if (value == 0) + value = Jim_NewEmptyStringObj(interp); + /* If value is a non-assignable one, skip it */ + if (descr->pos == -1) { + Jim_FreeNewObj(interp, value); + } + else if (descr->pos == 0) + /* Otherwise append it to the result list if no XPG3 was given */ + Jim_ListAppendElement(interp, resultList, value); + else if (resultVec[descr->pos - 1] == emptyStr) { + /* But due to given XPG3, put the value into the corr. slot */ + Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); + Jim_IncrRefCount(value); + resultVec[descr->pos - 1] = value; + } + else { + /* Otherwise, the slot was already used - free obj and ERROR */ + Jim_FreeNewObj(interp, value); + goto err; + } + } + Jim_DecrRefCount(interp, emptyStr); + return resultList; + eof: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return (Jim_Obj *)EOF; + err: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return 0; +} + +/* ----------------------------------------------------------------------------- + * Pseudo Random Number Generation + * ---------------------------------------------------------------------------*/ +/* Initialize the sbox with the numbers from 0 to 255 */ +static void JimPrngInit(Jim_Interp *interp) +{ +#define PRNG_SEED_SIZE 256 + int i; + unsigned int *seed; + time_t t = time(NULL); + + interp->prngState = Jim_Alloc(sizeof(Jim_PrngState)); + + seed = Jim_Alloc(PRNG_SEED_SIZE * sizeof(*seed)); + for (i = 0; i < PRNG_SEED_SIZE; i++) { + seed[i] = (rand() ^ t ^ clock()); + } + JimPrngSeed(interp, (unsigned char *)seed, PRNG_SEED_SIZE * sizeof(*seed)); + Jim_Free(seed); +} + +/* Generates N bytes of random data */ +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len) +{ + Jim_PrngState *prng; + unsigned char *destByte = (unsigned char *)dest; + unsigned int si, sj, x; + + /* initialization, only needed the first time */ + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + /* generates 'len' bytes of pseudo-random numbers */ + for (x = 0; x < len; x++) { + prng->i = (prng->i + 1) & 0xff; + si = prng->sbox[prng->i]; + prng->j = (prng->j + si) & 0xff; + sj = prng->sbox[prng->j]; + prng->sbox[prng->i] = sj; + prng->sbox[prng->j] = si; + *destByte++ = prng->sbox[(si + sj) & 0xff]; + } +} + +/* Re-seed the generator with user-provided bytes */ +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) +{ + int i; + Jim_PrngState *prng; + + /* initialization, only needed the first time */ + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + + /* Set the sbox[i] with i */ + for (i = 0; i < 256; i++) + prng->sbox[i] = i; + /* Now use the seed to perform a random permutation of the sbox */ + for (i = 0; i < seedLen; i++) { + unsigned char t; + + t = prng->sbox[i & 0xFF]; + prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; + prng->sbox[seed[i]] = t; + } + prng->i = prng->j = 0; + + /* discard at least the first 256 bytes of stream. + * borrow the seed buffer for this + */ + for (i = 0; i < 256; i += seedLen) { + JimRandomBytes(interp, seed, seedLen); + } +} + +/* [incr] */ +static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide wideValue, increment = 1; + Jim_Obj *intObjPtr; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) + return JIM_ERR; + } + intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!intObjPtr) { + /* Set missing variable to 0 */ + wideValue = 0; + } + else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { + return JIM_ERR; + } + if (!intObjPtr || Jim_IsShared(intObjPtr)) { + intObjPtr = Jim_NewIntObj(interp, wideValue + increment); + if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, intObjPtr); + return JIM_ERR; + } + } + else { + /* Can do it the quick way */ + Jim_InvalidateStringRep(intObjPtr); + JimWideValue(intObjPtr) = wideValue + increment; + + /* The following step is required in order to invalidate the + * string repr of "FOO" if the var name is on the form of "FOO(IDX)" */ + if (argv[1]->typePtr != &variableObjType) { + /* Note that this can't fail since GetVariable already succeeded */ + Jim_SetVariable(interp, argv[1], intObjPtr); + } + } + Jim_SetResult(interp, intObjPtr); + return JIM_OK; +} + + +/* ----------------------------------------------------------------------------- + * Eval + * ---------------------------------------------------------------------------*/ +#define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */ +#define JIM_EVAL_SINTV_LEN 8 /* static interpolation vector length */ + +/* Handle calls to the [unknown] command */ +static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *fileNameObj, + int linenr) +{ + Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN]; + int retCode; + + /* If JimUnknown() is recursively called too many times... + * done here + */ + if (interp->unknown_called > 50) { + return JIM_ERR; + } + + /* If the [unknown] command does not exists returns + * just now */ + if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) + return JIM_ERR; + + /* The object interp->unknown just contains + * the "unknown" string, it is used in order to + * avoid to lookup the unknown command every time + * but instread to cache the result. */ + if (argc + 1 <= JIM_EVAL_SARGV_LEN) + v = sv; + else + v = Jim_Alloc(sizeof(Jim_Obj *) * (argc + 1)); + /* Make a copy of the arguments vector, but shifted on + * the right of one position. The command name of the + * command will be instead the first argument of the + * [unknown] call. */ + memcpy(v + 1, argv, sizeof(Jim_Obj *) * argc); + v[0] = interp->unknown; + /* Call it */ + interp->unknown_called++; + retCode = JimEvalObjVector(interp, argc + 1, v, fileNameObj, linenr); + interp->unknown_called--; + + /* Clean up */ + if (v != sv) + Jim_Free(v); + return retCode; +} + +/* Eval the object vector 'objv' composed of 'objc' elements. + * Every element is used as single argument. + * Jim_EvalObj() will call this function every time its object + * argument is of "list" type, with no string representation. + * + * This is possible because the string representation of a + * list object generated by the UpdateStringOfList is made + * in a way that ensures that every list element is a different + * command argument. */ +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, + Jim_Obj *fileNameObj, int linenr) +{ + int i, retcode; + Jim_Cmd *cmdPtr; + + /* Incr refcount of arguments. */ + for (i = 0; i < objc; i++) + Jim_IncrRefCount(objv[i]); + /* Command lookup */ + cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); + if (cmdPtr == NULL) { + retcode = JimUnknown(interp, objc, objv, fileNameObj, linenr); + } + else { + /* Call it -- Make sure result is an empty object. */ + JimIncrCmdRefCount(cmdPtr); + Jim_SetEmptyResult(interp); + if (cmdPtr->isproc) { + retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv); + } + else { + interp->cmdPrivData = cmdPtr->u.native.privData; + retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); + } + JimDecrCmdRefCount(interp, cmdPtr); + } + /* Decr refcount of arguments and return the retcode */ + for (i = 0; i < objc; i++) + Jim_DecrRefCount(interp, objv[i]); + + return retcode; +} + +int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + return JimEvalObjVector(interp, objc, objv, interp->emptyObj, 1); +} + +/** + * Invokes 'prefix' as a command with the objv array as arguments. + */ +int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv) +{ + int i; + int ret; + Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv)); + + nargv[0] = prefix; + for (i = 0; i < objc; i++) { + nargv[i + 1] = objv[i]; + } + ret = Jim_EvalObjVector(interp, objc + 1, nargv); + Jim_Free(nargv); + return ret; +} + +static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNameObj, int line) +{ + int rc = retcode; + + if (rc == JIM_ERR && !interp->errorFlag) { + /* This is the first error, so save the file/line information and reset the stack */ + interp->errorFlag = 1; + Jim_IncrRefCount(fileNameObj); + Jim_DecrRefCount(interp, interp->errorFileNameObj); + interp->errorFileNameObj = fileNameObj; + interp->errorLine = line; + + JimResetStackTrace(interp); + /* Always add a level where the error first occurs */ + interp->addStackTrace++; + } + + /* Now if this is an "interesting" level, add it to the stack trace */ + if (rc == JIM_ERR && interp->addStackTrace > 0) { + /* Add the stack info for the current level */ + + JimAppendStackTrace(interp, Jim_String(interp->errorProc), fileNameObj, line); + + /* Note: if we didn't have a filename for this level, + * don't clear the addStackTrace flag + * so we can pick it up at the next level + */ + if (Jim_Length(fileNameObj)) { + interp->addStackTrace = 0; + } + + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = interp->emptyObj; + Jim_IncrRefCount(interp->errorProc); + } + else if (rc == JIM_RETURN && interp->returnCode == JIM_ERR) { + /* Propagate the addStackTrace value through 'return -code error' */ + } + else { + interp->addStackTrace = 0; + } +} + +/* And delete any local procs */ +static void JimDeleteLocalProcs(Jim_Interp *interp) +{ + if (interp->localProcs) { + char *procname; + + while ((procname = Jim_StackPop(interp->localProcs)) != NULL) { + /* If there is a pushed command, find it */ + Jim_Cmd *prevCmd = NULL; + Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, procname); + if (he) { + Jim_Cmd *cmd = (Jim_Cmd *)he->u.val; + if (cmd->isproc && cmd->u.proc.prevCmd) { + prevCmd = cmd->u.proc.prevCmd; + cmd->u.proc.prevCmd = NULL; + } + } + + /* Delete the local proc */ + Jim_DeleteCommand(interp, procname); + + if (prevCmd) { + /* And restore the pushed command */ + Jim_AddHashEntry(&interp->commands, procname, prevCmd); + } + Jim_Free(procname); + } + Jim_FreeStack(interp->localProcs); + Jim_Free(interp->localProcs); + interp->localProcs = NULL; + } +} + +static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr) +{ + Jim_Obj *objPtr; + + switch (token->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + objPtr = token->objPtr; + break; + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, token->objPtr, JIM_ERRMSG); + break; + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, token->objPtr); + break; + case JIM_TT_EXPRSUGAR: + objPtr = JimExpandExprSugar(interp, token->objPtr); + break; + case JIM_TT_CMD: + switch (Jim_EvalObj(interp, token->objPtr)) { + case JIM_OK: + case JIM_RETURN: + objPtr = interp->result; + break; + case JIM_BREAK: + /* Stop substituting */ + return JIM_BREAK; + case JIM_CONTINUE: + /* just skip this one */ + return JIM_CONTINUE; + default: + return JIM_ERR; + } + break; + default: + JimPanic((1, + "default token type (%d) reached " "in Jim_SubstObj().", token->type)); + objPtr = NULL; + break; + } + if (objPtr) { + *objPtrPtr = objPtr; + return JIM_OK; + } + return JIM_ERR; +} + +/* Interpolate the given tokens into a unique Jim_Obj returned by reference + * via *objPtrPtr. This function is only called by Jim_EvalObj() and Jim_SubstObj() + * The returned object has refcount = 0. + */ +static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags) +{ + int totlen = 0, i; + Jim_Obj **intv; + Jim_Obj *sintv[JIM_EVAL_SINTV_LEN]; + Jim_Obj *objPtr; + char *s; + + if (tokens <= JIM_EVAL_SINTV_LEN) + intv = sintv; + else + intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens); + + /* Compute every token forming the argument + * in the intv objects vector. */ + for (i = 0; i < tokens; i++) { + switch (JimSubstOneToken(interp, &token[i], &intv[i])) { + case JIM_OK: + case JIM_RETURN: + break; + case JIM_BREAK: + if (flags & JIM_SUBST_FLAG) { + /* Stop here */ + tokens = i; + continue; + } + /* XXX: Should probably set an error about break outside loop */ + /* fall through to error */ + case JIM_CONTINUE: + if (flags & JIM_SUBST_FLAG) { + intv[i] = NULL; + continue; + } + /* XXX: Ditto continue outside loop */ + /* fall through to error */ + default: + while (i--) { + Jim_DecrRefCount(interp, intv[i]); + } + if (intv != sintv) { + Jim_Free(intv); + } + return NULL; + } + Jim_IncrRefCount(intv[i]); + Jim_String(intv[i]); + totlen += intv[i]->length; + } + + /* Fast path return for a single token */ + if (tokens == 1 && intv[0] && intv == sintv) { + Jim_DecrRefCount(interp, intv[0]); + return intv[0]; + } + + /* Concatenate every token in an unique + * object. */ + objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); + + if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC + && token[2].type == JIM_TT_VAR) { + /* May be able to do fast interpolated object -> dictSubst */ + objPtr->typePtr = &interpolatedObjType; + objPtr->internalRep.twoPtrValue.ptr1 = (void *)token; + objPtr->internalRep.twoPtrValue.ptr2 = intv[2]; + Jim_IncrRefCount(intv[2]); + } + + s = objPtr->bytes = Jim_Alloc(totlen + 1); + objPtr->length = totlen; + for (i = 0; i < tokens; i++) { + if (intv[i]) { + memcpy(s, intv[i]->bytes, intv[i]->length); + s += intv[i]->length; + Jim_DecrRefCount(interp, intv[i]); + } + } + objPtr->bytes[totlen] = '\0'; + /* Free the intv vector if not static. */ + if (intv != sintv) { + Jim_Free(intv); + } + + return objPtr; +} + + +/* If listPtr is a list, call JimEvalObjVector() with the given source info. + * Otherwise eval with Jim_EvalObj() + */ +static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *fileNameObj, int linenr) +{ + if (!Jim_IsList(listPtr)) { + return Jim_EvalObj(interp, listPtr); + } + else { + int retcode = JIM_OK; + + if (listPtr->internalRep.listValue.len) { + Jim_IncrRefCount(listPtr); + retcode = JimEvalObjVector(interp, + listPtr->internalRep.listValue.len, + listPtr->internalRep.listValue.ele, fileNameObj, linenr); + Jim_DecrRefCount(interp, listPtr); + } + return retcode; + } +} + +int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) +{ + int i; + ScriptObj *script; + ScriptToken *token; + int retcode = JIM_OK; + Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL; + int linenr = 0; + + interp->errorFlag = 0; + + /* If the object is of type "list", with no string rep we can call + * a specialized version of Jim_EvalObj() */ + if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { + return JimEvalObjList(interp, scriptObjPtr, interp->emptyObj, 1); + } + + Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */ + script = Jim_GetScript(interp, scriptObjPtr); + + /* Reset the interpreter result. This is useful to + * return the empty result in the case of empty program. */ + Jim_SetEmptyResult(interp); + +#ifdef JIM_OPTIMIZATION + /* Check for one of the following common scripts used by for, while + * + * {} + * incr a + */ + if (script->len == 0) { + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_OK; + } + if (script->len == 3 + && script->token[1].objPtr->typePtr == &commandObjType + && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0 + && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand + && script->token[2].objPtr->typePtr == &variableObjType) { + + Jim_Obj *objPtr = Jim_GetVariable(interp, script->token[2].objPtr, JIM_NONE); + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + JimWideValue(objPtr)++; + Jim_InvalidateStringRep(objPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } +#endif + + /* Now we have to make sure the internal repr will not be + * freed on shimmering. + * + * Think for example to this: + * + * set x {llength $x; ... some more code ...}; eval $x + * + * In order to preserve the internal rep, we increment the + * inUse field of the script internal rep structure. */ + script->inUse++; + + token = script->token; + argv = sargv; + + /* Execute every command sequentially until the end of the script + * or an error occurs. + */ + for (i = 0; i < script->len && retcode == JIM_OK; ) { + int argc; + int j; + Jim_Cmd *cmd; + + /* First token of the line is always JIM_TT_LINE */ + argc = token[i].objPtr->internalRep.scriptLineValue.argc; + linenr = token[i].objPtr->internalRep.scriptLineValue.line; + + /* Allocate the arguments vector if required */ + if (argc > JIM_EVAL_SARGV_LEN) + argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); + + /* Skip the JIM_TT_LINE token */ + i++; + + /* Populate the arguments objects. + * If an error occurs, retcode will be set and + * 'j' will be set to the number of args expanded + */ + for (j = 0; j < argc; j++) { + long wordtokens = 1; + int expand = 0; + Jim_Obj *wordObjPtr = NULL; + + if (token[i].type == JIM_TT_WORD) { + wordtokens = JimWideValue(token[i++].objPtr); + if (wordtokens < 0) { + expand = 1; + wordtokens = -wordtokens; + } + } + + if (wordtokens == 1) { + /* Fast path if the token does not + * need interpolation */ + + switch (token[i].type) { + case JIM_TT_ESC: + case JIM_TT_STR: + wordObjPtr = token[i].objPtr; + break; + case JIM_TT_VAR: + wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG); + break; + case JIM_TT_EXPRSUGAR: + wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr); + break; + case JIM_TT_DICTSUGAR: + wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr); + break; + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, token[i].objPtr); + if (retcode == JIM_OK) { + wordObjPtr = Jim_GetResult(interp); + } + break; + default: + JimPanic((1, "default token type reached " "in Jim_EvalObj().")); + } + } + else { + /* For interpolation we call a helper + * function to do the work for us. */ + wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE); + } + + if (!wordObjPtr) { + if (retcode == JIM_OK) { + retcode = JIM_ERR; + } + break; + } + + Jim_IncrRefCount(wordObjPtr); + i += wordtokens; + + if (!expand) { + argv[j] = wordObjPtr; + } + else { + /* Need to expand wordObjPtr into multiple args from argv[j] ... */ + int len = Jim_ListLength(interp, wordObjPtr); + int newargc = argc + len - 1; + int k; + + if (len > 1) { + if (argv == sargv) { + if (newargc > JIM_EVAL_SARGV_LEN) { + argv = Jim_Alloc(sizeof(*argv) * newargc); + memcpy(argv, sargv, sizeof(*argv) * j); + } + } + else { + /* Need to realloc to make room for (len - 1) more entries */ + argv = Jim_Realloc(argv, sizeof(*argv) * newargc); + } + } + + /* Now copy in the expanded version */ + for (k = 0; k < len; k++) { + argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; + Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); + } + + /* The original object reference is no longer needed, + * after the expansion it is no longer present on + * the argument vector, but the single elements are + * in its place. */ + Jim_DecrRefCount(interp, wordObjPtr); + + /* And update the indexes */ + j--; + argc += len - 1; + } + } + + if (retcode == JIM_OK && argc) { + /* Lookup the command to call */ + cmd = Jim_GetCommand(interp, argv[0], JIM_ERRMSG); + if (cmd != NULL) { + /* Call it -- Make sure result is an empty object. */ + JimIncrCmdRefCount(cmd); + Jim_SetEmptyResult(interp); + if (cmd->isproc) { + retcode = + JimCallProcedure(interp, cmd, script->fileNameObj, linenr, argc, argv); + } else { + interp->cmdPrivData = cmd->u.native.privData; + retcode = cmd->u.native.cmdProc(interp, argc, argv); + } + JimDecrCmdRefCount(interp, cmd); + } + else { + /* Call [unknown] */ + retcode = JimUnknown(interp, argc, argv, script->fileNameObj, linenr); + } + if (interp->signal_level && interp->sigmask) { + /* Check for a signal after each command */ + retcode = JIM_SIGNAL; + } + } + + /* Finished with the command, so decrement ref counts of each argument */ + while (j-- > 0) { + Jim_DecrRefCount(interp, argv[j]); + } + + if (argv != sargv) { + Jim_Free(argv); + argv = sargv; + } + } + + /* Possibly add to the error stack trace */ + JimAddErrorToStack(interp, retcode, script->fileNameObj, linenr); + + /* Note that we don't have to decrement inUse, because the + * following code transfers our use of the reference again to + * the script object. */ + Jim_FreeIntRep(interp, scriptObjPtr); + scriptObjPtr->typePtr = &scriptObjType; + Jim_SetIntRepPtr(scriptObjPtr, script); + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) +{ + int retcode; + /* If argObjPtr begins with '&', do an automatic upvar */ + const char *varname = Jim_String(argNameObj); + if (*varname == '&') { + /* First check that the target variable exists */ + Jim_Obj *objPtr; + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = interp->framePtr->parentCallFrame; + objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); + interp->framePtr = savedCallFrame; + if (!objPtr) { + return JIM_ERR; + } + + /* It exists, so perform the binding. */ + objPtr = Jim_NewStringObj(interp, varname + 1, -1); + Jim_IncrRefCount(objPtr); + retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parentCallFrame); + Jim_DecrRefCount(interp, objPtr); + } + else { + retcode = Jim_SetVariable(interp, argNameObj, argValObj); + } + return retcode; +} + +/** + * Sets the interp result to be an error message indicating the required proc args. + */ +static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) +{ + /* Create a nice error message, consistent with Tcl 8.5 */ + Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); + int i; + + for (i = 0; i < cmd->u.proc.argListLen; i++) { + Jim_AppendString(interp, argmsg, " ", 1); + + if (i == cmd->u.proc.argsPos) { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + /* Renamed args */ + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); + Jim_AppendString(interp, argmsg, " ...?", -1); + } + else { + /* We have plain args */ + Jim_AppendString(interp, argmsg, "?argument ...?", -1); + } + } + else { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); + Jim_AppendString(interp, argmsg, "?", 1); + } + else { + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); + } + } + } + Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); + Jim_FreeNewObj(interp, argmsg); +} + +/* Call a procedure implemented in Tcl. + * It's possible to speed-up a lot this function, currently + * the callframes are not cached, but allocated and + * destroied every time. What is expecially costly is + * to create/destroy the local vars hash table every time. + * + * This can be fixed just implementing callframes caching + * in JimCreateCallFrame() and JimFreeCallFrame(). */ +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, int argc, + Jim_Obj *const *argv) +{ + Jim_CallFrame *callFramePtr; + Jim_Stack *prevLocalProcs; + int i, d, retcode, optargs; + + /* Check arity */ + if (argc - 1 < cmd->u.proc.reqArity || + (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { + JimSetProcWrongArgs(interp, argv[0], cmd); + return JIM_ERR; + } + + /* Check if there are too nested calls */ + if (interp->framePtr->level == interp->maxNestingDepth) { + Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); + return JIM_ERR; + } + + /* Create a new callframe */ + callFramePtr = JimCreateCallFrame(interp, interp->framePtr); + callFramePtr->argv = argv; + callFramePtr->argc = argc; + callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; + callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; + callFramePtr->staticVars = cmd->u.proc.staticVars; + callFramePtr->fileNameObj = fileNameObj; + callFramePtr->line = linenr; + Jim_IncrRefCount(cmd->u.proc.argListObjPtr); + Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); + interp->framePtr = callFramePtr; + + /* How many optional args are available */ + optargs = (argc - 1 - cmd->u.proc.reqArity); + + /* Step 'i' along the actual args, and step 'd' along the formal args */ + i = 1; + for (d = 0; d < cmd->u.proc.argListLen; d++) { + Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; + if (d == cmd->u.proc.argsPos) { + /* assign $args */ + Jim_Obj *listObjPtr; + int argsLen = 0; + if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { + argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); + } + listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); + + /* It is possible to rename args. */ + if (cmd->u.proc.arglist[d].defaultObjPtr) { + nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; + } + retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); + if (retcode != JIM_OK) { + goto badargset; + } + + i += argsLen; + continue; + } + + /* Optional or required? */ + if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { + retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); + } + else { + /* Ran out, so use the default */ + retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); + } + if (retcode != JIM_OK) { + goto badargset; + } + } + + /* Install a new stack for local procs */ + prevLocalProcs = interp->localProcs; + interp->localProcs = NULL; + + /* Eval the body */ + retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); + + /* Delete any local procs */ + JimDeleteLocalProcs(interp); + interp->localProcs = prevLocalProcs; + +badargset: + /* Destroy the callframe */ + interp->framePtr = interp->framePtr->parentCallFrame; + if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); + } + else { + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); + } + /* Handle the JIM_EVAL return code */ + while (retcode == JIM_EVAL) { + Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); + + Jim_IncrRefCount(resultScriptObjPtr); + /* Should be a list! */ + retcode = JimEvalObjList(interp, resultScriptObjPtr, fileNameObj, linenr); + Jim_DecrRefCount(interp, resultScriptObjPtr); + } + /* Handle the JIM_RETURN return code */ + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + else if (retcode == JIM_ERR) { + interp->addStackTrace++; + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = argv[0]; + Jim_IncrRefCount(interp->errorProc); + } + return retcode; +} + +int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) +{ + int retval; + Jim_Obj *scriptObjPtr; + + scriptObjPtr = Jim_NewStringObj(interp, script, -1); + Jim_IncrRefCount(scriptObjPtr); + + if (filename) { + Jim_Obj *prevScriptObj; + + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retval = Jim_EvalObj(interp, scriptObjPtr); + + interp->currentScriptObj = prevScriptObj; + } + else { + retval = Jim_EvalObj(interp, scriptObjPtr); + } + Jim_DecrRefCount(interp, scriptObjPtr); + return retval; +} + +int Jim_Eval(Jim_Interp *interp, const char *script) +{ + return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1)); +} + +/* Execute script in the scope of the global level */ +int Jim_EvalGlobal(Jim_Interp *interp, const char *script) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_Eval(interp, script); + interp->framePtr = savedFramePtr; + + return retval; +} + +int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_EvalFile(interp, filename); + interp->framePtr = savedFramePtr; + + return retval; +} + +#include <sys/stat.h> + +int Jim_EvalFile(Jim_Interp *interp, const char *filename) +{ + FILE *fp; + char *buf; + Jim_Obj *scriptObjPtr; + Jim_Obj *prevScriptObj; + struct stat sb; + int retcode; + int readlen; + struct JimParseResult result; + + if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + if (sb.st_size == 0) { + fclose(fp); + return JIM_OK; + } + + buf = Jim_Alloc(sb.st_size + 1); + readlen = fread(buf, 1, sb.st_size, fp); + if (ferror(fp)) { + fclose(fp); + Jim_Free(buf); + Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + fclose(fp); + buf[readlen] = 0; + + scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); + Jim_IncrRefCount(scriptObjPtr); + + /* Now check the script for unmatched braces, etc. */ + if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) { + const char *msg; + char linebuf[20]; + + switch (result.missing) { + case '[': + msg = "unmatched \"[\""; + break; + case '{': + msg = "missing close-brace"; + break; + case '"': + default: + msg = "missing quote"; + break; + } + + snprintf(linebuf, sizeof(linebuf), "%d", result.line); + + Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s", + msg, filename, linebuf); + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_ERR; + } + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retcode = Jim_EvalObj(interp, scriptObjPtr); + + /* Handle the JIM_RETURN return code */ + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + if (retcode == JIM_ERR) { + /* EvalFile changes context, so add a stack frame here */ + interp->addStackTrace++; + } + + interp->currentScriptObj = prevScriptObj; + + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +/* ----------------------------------------------------------------------------- + * Subst + * ---------------------------------------------------------------------------*/ +static int JimParseSubstStr(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (pc->len && *pc->p != '$' && *pc->p != '[') { + if (*pc->p == '\\' && pc->len > 1) { + pc->p++; + pc->len--; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; +} + +static int JimParseSubst(struct JimParserCtx *pc, int flags) +{ + int retval; + + if (pc->len == 0) { + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*pc->p) { + case '[': + retval = JimParseCmd(pc); + if (flags & JIM_SUBST_NOCMD) { + pc->tstart--; + pc->tend++; + pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC; + } + return retval; + break; + case '$': + if (JimParseVar(pc) == JIM_ERR) { + pc->tstart = pc->tend = pc->p++; + pc->len--; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + } + else { + if (flags & JIM_SUBST_NOVAR) { + pc->tstart--; + if (flags & JIM_SUBST_NOESC) + pc->tt = JIM_TT_STR; + else + pc->tt = JIM_TT_ESC; + if (*pc->tstart == '{') { + pc->tstart--; + if (*(pc->tend + 1)) + pc->tend++; + } + } + } + break; + default: + retval = JimParseSubstStr(pc); + if (flags & JIM_SUBST_NOESC) + pc->tt = JIM_TT_STR; + return retval; + break; + } + return JIM_OK; +} + +/* The subst object type reuses most of the data structures and functions + * of the script object. Script's data structures are a bit more complex + * for what is needed for [subst]itution tasks, but the reuse helps to + * deal with a single data structure at the cost of some more memory + * usage for substitutions. */ + +/* This method takes the string representation of an object + * as a Tcl string where to perform [subst]itution, and generates + * the pre-parsed internal representation. */ +static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script = Jim_Alloc(sizeof(*script)); + ParseTokenList tokenlist; + + /* Initially parse the subst into tokens (in tokenlist) */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, 1); + while (1) { + JimParseSubst(&parser, flags); + if (parser.eof) { + /* Note that subst doesn't need the EOL token */ + break; + } + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + + /* Create the "real" subst/script tokens from the initial token list */ + script->inUse = 1; + script->substFlags = flags; + script->fileNameObj = interp->emptyObj; + Jim_IncrRefCount(script->fileNameObj); + SubstObjAddTokens(interp, script, &tokenlist); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + +#ifdef DEBUG_SHOW_SUBST + { + int i; + + printf("==== Subst ====\n"); + for (i = 0; i < script->len; i++) { + printf("[%2d] %s '%s'\n", i, jim_tt_name(script->token[i].type), + Jim_String(script->token[i].objPtr)); + } + } +#endif + + /* Free the old internal rep and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; + return JIM_OK; +} + +static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + if (objPtr->typePtr != &scriptObjType || ((ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags != flags) + SetSubstFromAny(interp, objPtr, flags); + return (ScriptObj *) Jim_GetIntRepPtr(objPtr); +} + +/* Performs commands,variables,blackslashes substitution, + * storing the result object (with refcount 0) into + * resObjPtrPtr. */ +int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) +{ + ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); + + Jim_IncrRefCount(substObjPtr); /* Make sure it's shared. */ + /* In order to preserve the internal rep, we increment the + * inUse field of the script internal rep structure. */ + script->inUse++; + + *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); + + script->inUse--; + Jim_DecrRefCount(interp, substObjPtr); + if (*resObjPtrPtr == NULL) { + return JIM_ERR; + } + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Core commands utility functions + * ---------------------------------------------------------------------------*/ +void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) +{ + int i; + Jim_Obj *objPtr = Jim_NewEmptyStringObj(interp); + + Jim_AppendString(interp, objPtr, "wrong # args: should be \"", -1); + for (i = 0; i < argc; i++) { + Jim_AppendObj(interp, objPtr, argv[i]); + if (!(i + 1 == argc && msg[0] == '\0')) + Jim_AppendString(interp, objPtr, " ", 1); + } + Jim_AppendString(interp, objPtr, msg, -1); + Jim_AppendString(interp, objPtr, "\"", 1); + Jim_SetResult(interp, objPtr); +} + +#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) + +/* type is: 0=commands, 1=procs, 2=channels */ +static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + /* Check for the non-pattern case. We can do this much more efficiently. */ + if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, patternObjPtr, JIM_NONE); + if (cmdPtr) { + if (type == 1 && !cmdPtr->isproc) { + /* not a proc */ + } + else if (type == 2 && !Jim_AioFilehandle(interp, patternObjPtr)) { + /* not a channel */ + } + else { + Jim_ListAppendElement(interp, listObjPtr, patternObjPtr); + } + } + return listObjPtr; + } + + htiter = Jim_GetHashTableIterator(&interp->commands); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_Cmd *cmdPtr = he->u.val; + Jim_Obj *cmdNameObj; + + if (type == 1 && !cmdPtr->isproc) { + /* not a proc */ + continue; + } + if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0)) + continue; + + cmdNameObj = Jim_NewStringObj(interp, he->key, -1); + + /* Is it a channel? */ + if (type == 2 && !Jim_AioFilehandle(interp, cmdNameObj)) { + Jim_FreeNewObj(interp, cmdNameObj); + continue; + } + + Jim_ListAppendElement(interp, listObjPtr, cmdNameObj); + } + Jim_FreeHashTableIterator(htiter); + return listObjPtr; +} + +/* Keep this in order */ +#define JIM_VARLIST_GLOBALS 0 +#define JIM_VARLIST_LOCALS 1 +#define JIM_VARLIST_VARS 2 + +static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + if (mode == JIM_VARLIST_GLOBALS) { + htiter = Jim_GetHashTableIterator(&interp->topFramePtr->vars); + } + else { + /* For [info locals], if we are at top level an emtpy list + * is returned. I don't agree, but we aim at compatibility (SS) */ + if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) + return listObjPtr; + htiter = Jim_GetHashTableIterator(&interp->framePtr->vars); + } + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_Var *varPtr = (Jim_Var *)he->u.val; + + if (mode == JIM_VARLIST_LOCALS) { + if (varPtr->linkFramePtr != NULL) + continue; + } + if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0)) + continue; + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); + } + Jim_FreeHashTableIterator(htiter); + return listObjPtr; +} + +static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, + Jim_Obj **objPtrPtr, int info_level_cmd) +{ + Jim_CallFrame *targetCallFrame; + + targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); + if (targetCallFrame == NULL) { + return JIM_ERR; + } + /* No proc call at toplevel callframe */ + if (targetCallFrame == interp->topFramePtr) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return JIM_ERR; + } + if (info_level_cmd) { + *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); + } + else { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); + Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); + *objPtrPtr = listObj; + } + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Core commands + * ---------------------------------------------------------------------------*/ + +/* fake [puts] -- not the real puts, just for debugging. */ +static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string"); + return JIM_ERR; + } + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) { + Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1); + return JIM_ERR; + } + else { + fputs(Jim_String(argv[2]), stdout); + } + } + else { + puts(Jim_String(argv[1])); + } + return JIM_OK; +} + +/* Helper for [+] and [*] */ +static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res; + double doubleValue, doubleRes; + int i; + + res = (op == JIM_EXPROP_ADD) ? 0 : 1; + + for (i = 1; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) + goto trydouble; + if (op == JIM_EXPROP_ADD) + res += wideValue; + else + res *= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + doubleRes = (double)res; + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_ADD) + doubleRes += doubleValue; + else + doubleRes *= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + +/* Helper for [-] and [/] */ +static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res = 0; + double doubleValue, doubleRes = 0; + int i = 2; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?"); + return JIM_ERR; + } + else if (argc == 2) { + /* The arity = 2 case is different. For [- x] returns -x, + * while [/ x] returns 1/x. */ + if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) { + return JIM_ERR; + } + else { + if (op == JIM_EXPROP_SUB) + doubleRes = -doubleValue; + else + doubleRes = 1.0 / doubleValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; + } + } + if (op == JIM_EXPROP_SUB) { + res = -wideValue; + Jim_SetResultInt(interp, res); + } + else { + doubleRes = 1.0 / wideValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + } + return JIM_OK; + } + else { + if (Jim_GetWide(interp, argv[1], &res) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleRes) + != JIM_OK) { + return JIM_ERR; + } + else { + goto trydouble; + } + } + } + for (i = 2; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { + doubleRes = (double)res; + goto trydouble; + } + if (op == JIM_EXPROP_SUB) + res -= wideValue; + else + res /= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_SUB) + doubleRes -= doubleValue; + else + doubleRes /= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + + +/* [+] */ +static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD); +} + +/* [*] */ +static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL); +} + +/* [-] */ +static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB); +} + +/* [/] */ +static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV); +} + +/* [set] */ +static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *objPtr; + + objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!objPtr) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + /* argc == 3 case. */ + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + +/* [unset] + * + * unset ?-nocomplain? ?--? ?varName ...? + */ +static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i = 1; + int complain = 1; + + while (i < argc) { + if (Jim_CompareStringImmediate(interp, argv[i], "--")) { + i++; + break; + } + if (Jim_CompareStringImmediate(interp, argv[i], "-nocomplain")) { + complain = 0; + i++; + continue; + } + break; + } + + while (i < argc) { + if (Jim_UnsetVariable(interp, argv[i], complain ? JIM_ERRMSG : JIM_NONE) != JIM_OK + && complain) { + return JIM_ERR; + } + i++; + } + return JIM_OK; +} + +/* [while] */ +static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "condition body"); + return JIM_ERR; + } + + /* The general purpose implementation of while starts here */ + while (1) { + int boolean, retval; + + if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) + return retval; + if (!boolean) + break; + + if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) { + switch (retval) { + case JIM_BREAK: + goto out; + break; + case JIM_CONTINUE: + continue; + break; + default: + return retval; + } + } + } + out: + Jim_SetEmptyResult(interp); + return JIM_OK; +} + +/* [for] */ +static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + int boolean = 1; + Jim_Obj *varNamePtr = NULL; + Jim_Obj *stopVarNamePtr = NULL; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "start test next body"); + return JIM_ERR; + } + + /* Do the initialisation */ + if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { + return retval; + } + + /* And do the first test now. Better for optimisation + * if we can do next/test at the bottom of the loop + */ + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + + /* Ready to do the body as follows: + * while (1) { + * body // check retcode + * next // check retcode + * test // check retcode/test bool + * } + */ + +#ifdef JIM_OPTIMIZATION + /* Check if the for is on the form: + * for ... {$i < CONST} {incr i} + * for ... {$i < $j} {incr i} + */ + if (retval == JIM_OK && boolean) { + ScriptObj *incrScript; + ExprByteCode *expr; + jim_wide stop, currentVal; + unsigned jim_wide procEpoch; + Jim_Obj *objPtr; + int cmpOffset; + + /* Do it only if there aren't shared arguments */ + expr = JimGetExpression(interp, argv[2]); + incrScript = Jim_GetScript(interp, argv[3]); + + /* Ensure proper lengths to start */ + if (incrScript->len != 3 || !expr || expr->len != 3) { + goto evalstart; + } + /* Ensure proper token types. */ + if (incrScript->token[1].type != JIM_TT_ESC || + expr->token[0].type != JIM_TT_VAR || + (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { + goto evalstart; + } + + if (expr->token[2].type == JIM_EXPROP_LT) { + cmpOffset = 0; + } + else if (expr->token[2].type == JIM_EXPROP_LTE) { + cmpOffset = 1; + } + else { + goto evalstart; + } + + /* Update command must be incr */ + if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { + goto evalstart; + } + + /* incr, expression must be about the same variable */ + if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { + goto evalstart; + } + + /* Get the stop condition (must be a variable or integer) */ + if (expr->token[1].type == JIM_TT_EXPR_INT) { + if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { + goto evalstart; + } + } + else { + stopVarNamePtr = expr->token[1].objPtr; + Jim_IncrRefCount(stopVarNamePtr); + /* Keep the compiler happy */ + stop = 0; + } + + /* Initialization */ + procEpoch = interp->procEpoch; + varNamePtr = expr->token[0].objPtr; + Jim_IncrRefCount(varNamePtr); + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { + goto testcond; + } + + /* --- OPTIMIZED FOR --- */ + while (retval == JIM_OK) { + /* === Check condition === */ + /* Note that currentVal is already set here */ + + /* Immediate or Variable? get the 'stop' value if the latter. */ + if (stopVarNamePtr) { + objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { + goto testcond; + } + } + + if (currentVal >= stop + cmpOffset) { + break; + } + + /* Eval body */ + retval = Jim_EvalObj(interp, argv[4]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + retval = JIM_OK; + /* If there was a change in procedures/command continue + * with the usual [for] command implementation */ + if (procEpoch != interp->procEpoch) { + goto evalnext; + } + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); + + /* Increment */ + if (objPtr == NULL) { + retval = JIM_ERR; + goto out; + } + if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + currentVal = ++JimWideValue(objPtr); + Jim_InvalidateStringRep(objPtr); + } + else { + if (Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK || + Jim_SetVariable(interp, varNamePtr, Jim_NewIntObj(interp, + ++currentVal)) != JIM_OK) { + goto evalnext; + } + } + } + } + goto out; + } + evalstart: +#endif + + while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { + /* Body */ + retval = Jim_EvalObj(interp, argv[4]); + + if (retval == JIM_OK || retval == JIM_CONTINUE) { + /* increment */ + evalnext: + retval = Jim_EvalObj(interp, argv[3]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + /* test */ + testcond: + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + } + } + } + out: + if (stopVarNamePtr) { + Jim_DecrRefCount(interp, stopVarNamePtr); + } + if (varNamePtr) { + Jim_DecrRefCount(interp, varNamePtr); + } + + if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + + return retval; +} + +/* [loop] */ +static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + jim_wide i; + jim_wide limit; + jim_wide incr = 1; + Jim_Obj *bodyObjPtr; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body"); + return JIM_ERR; + } + + if (Jim_GetWide(interp, argv[2], &i) != JIM_OK || + Jim_GetWide(interp, argv[3], &limit) != JIM_OK || + (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) { + return JIM_ERR; + } + bodyObjPtr = (argc == 5) ? argv[4] : argv[5]; + + retval = Jim_SetVariable(interp, argv[1], argv[2]); + + while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) { + retval = Jim_EvalObj(interp, bodyObjPtr); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + + retval = JIM_OK; + + /* Increment */ + i += incr; + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + return JIM_ERR; + } + } + JimWideValue(objPtr) = i; + Jim_InvalidateStringRep(objPtr); + + /* The following step is required in order to invalidate the + * string repr of "FOO" if the var name is of the form of "FOO(IDX)" */ + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + retval = JIM_ERR; + break; + } + } + } + else { + objPtr = Jim_NewIntObj(interp, i); + retval = Jim_SetVariable(interp, argv[1], objPtr); + if (retval != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + } + } + } + } + + if (retval == JIM_OK || retval == JIM_CONTINUE || retval == JIM_BREAK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + return retval; +} + +/* foreach + lmap implementation. */ +static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) +{ + int result = JIM_ERR, i, nbrOfLists, *listsIdx, *listsEnd; + int nbrOfLoops = 0; + Jim_Obj *emptyStr, *script, *mapRes = NULL; + + if (argc < 4 || argc % 2 != 0) { + Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); + return JIM_ERR; + } + if (doMap) { + mapRes = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(mapRes); + } + emptyStr = Jim_NewEmptyStringObj(interp); + Jim_IncrRefCount(emptyStr); + script = argv[argc - 1]; /* Last argument is a script */ + nbrOfLists = (argc - 1 - 1) / 2; /* argc - 'foreach' - script */ + listsIdx = (int *)Jim_Alloc(nbrOfLists * sizeof(int)); + listsEnd = (int *)Jim_Alloc(nbrOfLists * 2 * sizeof(int)); + /* Initialize iterators and remember max nbr elements each list */ + memset(listsIdx, 0, nbrOfLists * sizeof(int)); + /* Remember lengths of all lists and calculate how much rounds to loop */ + for (i = 0; i < nbrOfLists * 2; i += 2) { + div_t cnt; + int count; + + listsEnd[i] = Jim_ListLength(interp, argv[i + 1]); + listsEnd[i + 1] = Jim_ListLength(interp, argv[i + 2]); + if (listsEnd[i] == 0) { + Jim_SetResultString(interp, "foreach varlist is empty", -1); + goto err; + } + cnt = div(listsEnd[i + 1], listsEnd[i]); + count = cnt.quot + (cnt.rem ? 1 : 0); + if (count > nbrOfLoops) + nbrOfLoops = count; + } + for (; nbrOfLoops-- > 0;) { + for (i = 0; i < nbrOfLists; ++i) { + int varIdx = 0, var = i * 2; + + while (varIdx < listsEnd[var]) { + Jim_Obj *varName, *ele; + int lst = i * 2 + 1; + + /* List index operations below can't fail */ + Jim_ListIndex(interp, argv[var + 1], varIdx, &varName, JIM_NONE); + if (listsIdx[i] < listsEnd[lst]) { + Jim_ListIndex(interp, argv[lst + 1], listsIdx[i], &ele, JIM_NONE); + /* Avoid shimmering */ + Jim_IncrRefCount(ele); + result = Jim_SetVariable(interp, varName, ele); + Jim_DecrRefCount(interp, ele); + if (result == JIM_OK) { + ++listsIdx[i]; /* Remember next iterator of current list */ + ++varIdx; /* Next variable */ + continue; + } + } + else if (Jim_SetVariable(interp, varName, emptyStr) == JIM_OK) { + ++varIdx; /* Next variable */ + continue; + } + goto err; + } + } + switch (result = Jim_EvalObj(interp, script)) { + case JIM_OK: + if (doMap) + Jim_ListAppendElement(interp, mapRes, interp->result); + break; + case JIM_CONTINUE: + break; + case JIM_BREAK: + goto out; + break; + default: + goto err; + } + } + out: + result = JIM_OK; + if (doMap) + Jim_SetResult(interp, mapRes); + else + Jim_SetEmptyResult(interp); + err: + if (doMap) + Jim_DecrRefCount(interp, mapRes); + Jim_DecrRefCount(interp, emptyStr); + Jim_Free(listsIdx); + Jim_Free(listsEnd); + return result; +} + +/* [foreach] */ +static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 0); +} + +/* [lmap] */ +static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 1); +} + +/* [if] */ +static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int boolean, retval, current = 1, falsebody = 0; + + if (argc >= 3) { + while (1) { + /* Far not enough arguments given! */ + if (current >= argc) + goto err; + if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) + != JIM_OK) + return retval; + /* There lacks something, isn't it? */ + if (current >= argc) + goto err; + if (Jim_CompareStringImmediate(interp, argv[current], "then")) + current++; + /* Tsk tsk, no then-clause? */ + if (current >= argc) + goto err; + if (boolean) + return Jim_EvalObj(interp, argv[current]); + /* Ok: no else-clause follows */ + if (++current >= argc) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + return JIM_OK; + } + falsebody = current++; + if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { + /* IIICKS - else-clause isn't last cmd? */ + if (current != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[current]); + } + else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) + /* Ok: elseif follows meaning all the stuff + * again (how boring...) */ + continue; + /* OOPS - else-clause is not last cmd? */ + else if (falsebody != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[falsebody]); + } + return JIM_OK; + } + err: + Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody"); + return JIM_ERR; +} + + +/* Returns 1 if match, 0 if no match or -<error> on error (e.g. -JIM_ERR, -JIM_BREAK)*/ +int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, + Jim_Obj *stringObj, int nocase) +{ + Jim_Obj *parms[4]; + int argc = 0; + long eq; + int rc; + + parms[argc++] = commandObj; + if (nocase) { + parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); + } + parms[argc++] = patternObj; + parms[argc++] = stringObj; + + rc = Jim_EvalObjVector(interp, argc, parms); + + if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { + eq = -rc; + } + + return eq; +} + +enum +{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; + +/* [switch] */ +static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; + Jim_Obj *command = 0, *const *caseList = 0, *strObj; + Jim_Obj *script = 0; + + if (argc < 3) { + wrongnumargs: + Jim_WrongNumArgs(interp, 1, argv, "?options? string " + "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); + return JIM_ERR; + } + for (opt = 1; opt < argc; ++opt) { + const char *option = Jim_String(argv[opt]); + + if (*option != '-') + break; + else if (strncmp(option, "--", 2) == 0) { + ++opt; + break; + } + else if (strncmp(option, "-exact", 2) == 0) + matchOpt = SWITCH_EXACT; + else if (strncmp(option, "-glob", 2) == 0) + matchOpt = SWITCH_GLOB; + else if (strncmp(option, "-regexp", 2) == 0) + matchOpt = SWITCH_RE; + else if (strncmp(option, "-command", 2) == 0) { + matchOpt = SWITCH_CMD; + if ((argc - opt) < 2) + goto wrongnumargs; + command = argv[++opt]; + } + else { + Jim_SetResultFormatted(interp, + "bad option \"%#s\": must be -exact, -glob, -regexp, -command procname or --", + argv[opt]); + return JIM_ERR; + } + if ((argc - opt) < 2) + goto wrongnumargs; + } + strObj = argv[opt++]; + patCount = argc - opt; + if (patCount == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + else + caseList = &argv[opt]; + if (patCount == 0 || patCount % 2 != 0) + goto wrongnumargs; + for (i = 0; script == 0 && i < patCount; i += 2) { + Jim_Obj *patObj = caseList[i]; + + if (!Jim_CompareStringImmediate(interp, patObj, "default") + || i < (patCount - 2)) { + switch (matchOpt) { + case SWITCH_EXACT: + if (Jim_StringEqObj(strObj, patObj)) + script = caseList[i + 1]; + break; + case SWITCH_GLOB: + if (Jim_StringMatchObj(interp, patObj, strObj, 0)) + script = caseList[i + 1]; + break; + case SWITCH_RE: + command = Jim_NewStringObj(interp, "regexp", -1); + /* Fall thru intentionally */ + case SWITCH_CMD:{ + int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); + + /* After the execution of a command we need to + * make sure to reconvert the object into a list + * again. Only for the single-list style [switch]. */ + if (argc - opt == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + /* command is here already decref'd */ + if (rc < 0) { + return -rc; + } + if (rc) + script = caseList[i + 1]; + break; + } + } + } + else { + script = caseList[i + 1]; + } + } + for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) + script = caseList[i + 1]; + if (script && Jim_CompareStringImmediate(interp, script, "-")) { + Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); + return JIM_ERR; + } + Jim_SetEmptyResult(interp); + if (script) { + return Jim_EvalObj(interp, script); + } + return JIM_OK; +} + +/* [list] */ +static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + + listObjPtr = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + +/* [lindex] */ +static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr, *listObjPtr; + int i; + int idx; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "list index ?...?"); + return JIM_ERR; + } + objPtr = argv[1]; + Jim_IncrRefCount(objPtr); + for (i = 2; i < argc; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) { + Jim_DecrRefCount(interp, listObjPtr); + return JIM_ERR; + } + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) { + /* Returns an empty object if the index + * is out of range. */ + Jim_DecrRefCount(interp, listObjPtr); + Jim_SetEmptyResult(interp); + return JIM_OK; + } + Jim_IncrRefCount(objPtr); + Jim_DecrRefCount(interp, listObjPtr); + } + Jim_SetResult(interp, objPtr); + Jim_DecrRefCount(interp, objPtr); + return JIM_OK; +} + +/* [llength] */ +static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1])); + return JIM_OK; +} + +/* [lsearch] */ +static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command", + NULL + }; + enum + { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE, + OPT_COMMAND }; + int i; + int opt_bool = 0; + int opt_not = 0; + int opt_nocase = 0; + int opt_all = 0; + int opt_inline = 0; + int opt_match = OPT_EXACT; + int listlen; + int rc = JIM_OK; + Jim_Obj *listObjPtr = NULL; + Jim_Obj *commandObj = NULL; + + if (argc < 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value"); + return JIM_ERR; + } + + for (i = 1; i < argc - 2; i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_BOOL: + opt_bool = 1; + opt_inline = 0; + break; + case OPT_NOT: + opt_not = 1; + break; + case OPT_NOCASE: + opt_nocase = 1; + break; + case OPT_INLINE: + opt_inline = 1; + opt_bool = 0; + break; + case OPT_ALL: + opt_all = 1; + break; + case OPT_COMMAND: + if (i >= argc - 2) { + goto wrongargs; + } + commandObj = argv[++i]; + /* fallthru */ + case OPT_EXACT: + case OPT_GLOB: + case OPT_REGEXP: + opt_match = option; + break; + } + } + + argv += i; + + if (opt_all) { + listObjPtr = Jim_NewListObj(interp, NULL, 0); + } + if (opt_match == OPT_REGEXP) { + commandObj = Jim_NewStringObj(interp, "regexp", -1); + } + if (commandObj) { + Jim_IncrRefCount(commandObj); + } + + listlen = Jim_ListLength(interp, argv[0]); + for (i = 0; i < listlen; i++) { + Jim_Obj *objPtr; + int eq = 0; + + Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE); + switch (opt_match) { + case OPT_EXACT: + eq = Jim_StringCompareObj(interp, objPtr, argv[1], opt_nocase) == 0; + break; + + case OPT_GLOB: + eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); + break; + + case OPT_REGEXP: + case OPT_COMMAND: + eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); + if (eq < 0) { + if (listObjPtr) { + Jim_FreeNewObj(interp, listObjPtr); + } + rc = JIM_ERR; + goto done; + } + break; + } + + /* If we have a non-match with opt_bool, opt_not, !opt_all, can't exit early */ + if (!eq && opt_bool && opt_not && !opt_all) { + continue; + } + + if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { + /* Got a match (or non-match for opt_not), or (opt_bool && opt_all) */ + Jim_Obj *resultObj; + + if (opt_bool) { + resultObj = Jim_NewIntObj(interp, eq ^ opt_not); + } + else if (!opt_inline) { + resultObj = Jim_NewIntObj(interp, i); + } + else { + resultObj = objPtr; + } + + if (opt_all) { + Jim_ListAppendElement(interp, listObjPtr, resultObj); + } + else { + Jim_SetResult(interp, resultObj); + goto done; + } + } + } + + if (opt_all) { + Jim_SetResult(interp, listObjPtr); + } + else { + /* No match */ + if (opt_bool) { + Jim_SetResultBool(interp, opt_not); + } + else if (!opt_inline) { + Jim_SetResultInt(interp, -1); + } + } + + done: + if (commandObj) { + Jim_DecrRefCount(interp, commandObj); + } + return rc; +} + +/* [lappend] */ +static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + int shared, i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); + return JIM_ERR; + } + listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!listObjPtr) { + /* Create the list if it does not exists */ + listObjPtr = Jim_NewListObj(interp, NULL, 0); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + } + shared = Jim_IsShared(listObjPtr); + if (shared) + listObjPtr = Jim_DuplicateObj(interp, listObjPtr); + for (i = 2; i < argc; i++) + Jim_ListAppendElement(interp, listObjPtr, argv[i]); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + if (shared) + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + +/* [linsert] */ +static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int idx, len; + Jim_Obj *listPtr; + + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "list index element " "?element ...?"); + return JIM_ERR; + } + listPtr = argv[1]; + if (Jim_IsShared(listPtr)) + listPtr = Jim_DuplicateObj(interp, listPtr); + if (Jim_GetIndex(interp, argv[2], &idx) != JIM_OK) + goto err; + len = Jim_ListLength(interp, listPtr); + if (idx >= len) + idx = len; + else if (idx < 0) + idx = len + idx + 1; + Jim_ListInsertElements(interp, listPtr, idx, argc - 3, &argv[3]); + Jim_SetResult(interp, listPtr); + return JIM_OK; + err: + if (listPtr != argv[1]) { + Jim_FreeNewObj(interp, listPtr); + } + return JIM_ERR; +} + +/* [lreplace] */ +static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int first, last, len, rangeLen; + Jim_Obj *listObj; + Jim_Obj *newListObj; + int i; + int shared; + + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last ?element element ...?"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK || + Jim_GetIndex(interp, argv[3], &last) != JIM_OK) { + return JIM_ERR; + } + + listObj = argv[1]; + len = Jim_ListLength(interp, listObj); + + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + + /* Now construct a new list which consists of: + * <elements before first> <supplied elements> <elements after last> + */ + + /* Check to see if trying to replace past the end of the list */ + if (first < len) { + /* OK. Not past the end */ + } + else if (len == 0) { + /* Special for empty list, adjust first to 0 */ + first = 0; + } + else { + Jim_SetResultString(interp, "list doesn't contain element ", -1); + Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); + return JIM_ERR; + } + + newListObj = Jim_NewListObj(interp, NULL, 0); + + shared = Jim_IsShared(listObj); + if (shared) { + listObj = Jim_DuplicateObj(interp, listObj); + } + + /* Add the first set of elements */ + for (i = 0; i < first; i++) { + Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]); + } + + /* Add supplied elements */ + for (i = 4; i < argc; i++) { + Jim_ListAppendElement(interp, newListObj, argv[i]); + } + + /* Add the remaining elements */ + for (i = first + rangeLen; i < len; i++) { + Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]); + } + Jim_SetResult(interp, newListObj); + if (shared) { + Jim_FreeNewObj(interp, listObj); + } + return JIM_OK; +} + +/* [lset] */ +static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); + return JIM_ERR; + } + else if (argc == 3) { + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; + } + if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]) + == JIM_ERR) + return JIM_ERR; + return JIM_OK; +} + +/* [lsort] */ +static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) +{ + static const char * const options[] = { + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL + }; + enum + { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX }; + Jim_Obj *resObj; + int i; + int retCode; + + struct lsort_info info; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? list"); + return JIM_ERR; + } + + info.type = JIM_LSORT_ASCII; + info.order = 1; + info.indexed = 0; + info.command = NULL; + info.interp = interp; + + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) + != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_ASCII: + info.type = JIM_LSORT_ASCII; + break; + case OPT_NOCASE: + info.type = JIM_LSORT_NOCASE; + break; + case OPT_INTEGER: + info.type = JIM_LSORT_INTEGER; + break; + case OPT_INCREASING: + info.order = 1; + break; + case OPT_DECREASING: + info.order = -1; + break; + case OPT_COMMAND: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); + return JIM_ERR; + } + info.type = JIM_LSORT_COMMAND; + info.command = argv[i + 1]; + i++; + break; + case OPT_INDEX: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) { + return JIM_ERR; + } + info.indexed = 1; + i++; + break; + } + } + resObj = Jim_DuplicateObj(interp, argv[argc - 1]); + retCode = ListSortElements(interp, resObj, &info); + if (retCode == JIM_OK) { + Jim_SetResult(interp, resObj); + } + else { + Jim_FreeNewObj(interp, resObj); + } + return retCode; +} + +/* [append] */ +static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *stringObjPtr; + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); + return JIM_ERR; + } + if (argc == 2) { + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!stringObjPtr) + return JIM_ERR; + } + else { + int freeobj = 0; + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!stringObjPtr) { + /* Create the string if it doesn't exist */ + stringObjPtr = Jim_NewEmptyStringObj(interp); + freeobj = 1; + } + else if (Jim_IsShared(stringObjPtr)) { + freeobj = 1; + stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); + } + for (i = 2; i < argc; i++) { + Jim_AppendObj(interp, stringObjPtr, argv[i]); + } + if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { + if (freeobj) { + Jim_FreeNewObj(interp, stringObjPtr); + } + return JIM_ERR; + } + } + Jim_SetResult(interp, stringObjPtr); + return JIM_OK; +} + +/* [debug] */ +static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#if defined(JIM_DEBUG_COMMAND) && !defined(JIM_BOOTSTRAP) + static const char * const options[] = { + "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen", + "exprbc", "show", + NULL + }; + enum + { + OPT_REFCOUNT, OPT_OBJCOUNT, OPT_OBJECTS, OPT_INVSTR, OPT_SCRIPTLEN, + OPT_EXPRLEN, OPT_EXPRBC, OPT_SHOW, + }; + int option; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + if (option == OPT_REFCOUNT) { + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + Jim_SetResultInt(interp, argv[2]->refCount); + return JIM_OK; + } + else if (option == OPT_OBJCOUNT) { + int freeobj = 0, liveobj = 0; + char buf[256]; + Jim_Obj *objPtr; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + /* Count the number of free objects. */ + objPtr = interp->freeList; + while (objPtr) { + freeobj++; + objPtr = objPtr->nextObjPtr; + } + /* Count the number of live objects. */ + objPtr = interp->liveList; + while (objPtr) { + liveobj++; + objPtr = objPtr->nextObjPtr; + } + /* Set the result string and return. */ + sprintf(buf, "free %d used %d", freeobj, liveobj); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; + } + else if (option == OPT_OBJECTS) { + Jim_Obj *objPtr, *listObjPtr, *subListObjPtr; + + /* Count the number of live objects. */ + objPtr = interp->liveList; + listObjPtr = Jim_NewListObj(interp, NULL, 0); + while (objPtr) { + char buf[128]; + const char *type = objPtr->typePtr ? objPtr->typePtr->name : ""; + + subListObjPtr = Jim_NewListObj(interp, NULL, 0); + sprintf(buf, "%p", objPtr); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, buf, -1)); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, type, -1)); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewIntObj(interp, objPtr->refCount)); + Jim_ListAppendElement(interp, subListObjPtr, objPtr); + Jim_ListAppendElement(interp, listObjPtr, subListObjPtr); + objPtr = objPtr->nextObjPtr; + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + else if (option == OPT_INVSTR) { + Jim_Obj *objPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + objPtr = argv[2]; + if (objPtr->typePtr != NULL) + Jim_InvalidateStringRep(objPtr); + Jim_SetEmptyResult(interp); + return JIM_OK; + } + else if (option == OPT_SHOW) { + const char *s; + int len, charlen; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + s = Jim_GetString(argv[2], &len); +#ifdef JIM_UTF8 + charlen = utf8_strlen(s, len); +#else + charlen = len; +#endif + printf("refcount: %d, type: %s\n", argv[2]->refCount, JimObjTypeName(argv[2])); + printf("chars (%d): <<%s>>\n", charlen, s); + printf("bytes (%d):", len); + while (len--) { + printf(" %02x", (unsigned char)*s++); + } + printf("\n"); + return JIM_OK; + } + else if (option == OPT_SCRIPTLEN) { + ScriptObj *script; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "script"); + return JIM_ERR; + } + script = Jim_GetScript(interp, argv[2]); + Jim_SetResultInt(interp, script->len); + return JIM_OK; + } + else if (option == OPT_EXPRLEN) { + ExprByteCode *expr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "expression"); + return JIM_ERR; + } + expr = JimGetExpression(interp, argv[2]); + if (expr == NULL) + return JIM_ERR; + Jim_SetResultInt(interp, expr->len); + return JIM_OK; + } + else if (option == OPT_EXPRBC) { + Jim_Obj *objPtr; + ExprByteCode *expr; + int i; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "expression"); + return JIM_ERR; + } + expr = JimGetExpression(interp, argv[2]); + if (expr == NULL) + return JIM_ERR; + objPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < expr->len; i++) { + const char *type; + const Jim_ExprOperator *op; + Jim_Obj *obj = expr->token[i].objPtr; + + switch (expr->token[i].type) { + case JIM_TT_EXPR_INT: + type = "int"; + break; + case JIM_TT_EXPR_DOUBLE: + type = "double"; + break; + case JIM_TT_CMD: + type = "command"; + break; + case JIM_TT_VAR: + type = "variable"; + break; + case JIM_TT_DICTSUGAR: + type = "dictsugar"; + break; + case JIM_TT_EXPRSUGAR: + type = "exprsugar"; + break; + case JIM_TT_ESC: + type = "subst"; + break; + case JIM_TT_STR: + type = "string"; + break; + default: + op = JimExprOperatorInfoByOpcode(expr->token[i].type); + if (op == NULL) { + type = "private"; + } + else { + type = "operator"; + } + obj = Jim_NewStringObj(interp, op ? op->name : "", -1); + break; + } + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, type, -1)); + Jim_ListAppendElement(interp, objPtr, obj); + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + else { + Jim_SetResultString(interp, + "bad option. Valid options are refcount, " "objcount, objects, invstr", -1); + return JIM_ERR; + } + /* unreached */ +#endif /* JIM_BOOTSTRAP */ +#if !defined(JIM_DEBUG_COMMAND) + Jim_SetResultString(interp, "unsupported", -1); + return JIM_ERR; +#endif +} + +/* [eval] */ +static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int rc; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "script ?...?"); + return JIM_ERR; + } + + if (argc == 2) { + rc = Jim_EvalObj(interp, argv[1]); + } + else { + rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + } + + if (rc == JIM_ERR) { + /* eval is "interesting", so add a stack frame here */ + interp->addStackTrace++; + } + return rc; +} + +/* [uplevel] */ +static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc >= 2) { + int retcode; + Jim_CallFrame *savedCallFrame, *targetCallFrame; + Jim_Obj *objPtr; + const char *str; + + /* Save the old callframe pointer */ + savedCallFrame = interp->framePtr; + + /* Lookup the target frame pointer */ + str = Jim_String(argv[1]); + if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { + targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + if (argc < 2) { + argv--; + Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); + return JIM_ERR; + } + /* Eval the code in the target callframe. */ + interp->framePtr = targetCallFrame; + if (argc == 2) { + retcode = Jim_EvalObj(interp, argv[1]); + } + else { + objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(objPtr); + retcode = Jim_EvalObj(interp, objPtr); + Jim_DecrRefCount(interp, objPtr); + } + interp->framePtr = savedCallFrame; + return retcode; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); + return JIM_ERR; + } +} + +/* [expr] */ +static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *exprResultPtr; + int retcode; + + if (argc == 2) { + retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); + } + else if (argc > 2) { + Jim_Obj *objPtr; + + objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(objPtr); + retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); + Jim_DecrRefCount(interp, objPtr); + } + else { + Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); + return JIM_ERR; + } + if (retcode != JIM_OK) + return retcode; + Jim_SetResult(interp, exprResultPtr); + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + +/* [break] */ +static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_BREAK; +} + +/* [continue] */ +static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_CONTINUE; +} + +/* [return] */ +static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_Obj *stackTraceObj = NULL; + Jim_Obj *errorCodeObj = NULL; + int returnCode = JIM_OK; + long level = 1; + + for (i = 1; i < argc - 1; i += 2) { + if (Jim_CompareStringImmediate(interp, argv[i], "-code")) { + if (Jim_GetReturnCode(interp, argv[i + 1], &returnCode) == JIM_ERR) { + return JIM_ERR; + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorinfo")) { + stackTraceObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorcode")) { + errorCodeObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-level")) { + if (Jim_GetLong(interp, argv[i + 1], &level) != JIM_OK || level < 0) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", argv[i + 1]); + return JIM_ERR; + } + } + else { + break; + } + } + + if (i != argc - 1 && i != argc) { + Jim_WrongNumArgs(interp, 1, argv, + "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); + } + + /* If a stack trace is supplied and code is error, set the stack trace */ + if (stackTraceObj && returnCode == JIM_ERR) { + JimSetStackTrace(interp, stackTraceObj); + } + /* If an error code list is supplied, set the global $errorCode */ + if (errorCodeObj && returnCode == JIM_ERR) { + Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); + } + interp->returnCode = returnCode; + interp->returnLevel = level; + + if (i == argc - 1) { + Jim_SetResult(interp, argv[i]); + } + return JIM_RETURN; +} + +/* [tailcall] */ +static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_SetResult(interp, objPtr); + return JIM_EVAL; +} + +/* [proc] */ +static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body"); + return JIM_ERR; + } + + if (argc == 4) { + return JimCreateProcedure(interp, argv[1], argv[2], NULL, argv[3]); + } + else { + return JimCreateProcedure(interp, argv[1], argv[2], argv[3], argv[4]); + } +} + +/* [local] */ +static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retcode; + + /* Evaluate the arguments with 'local' in force */ + interp->local++; + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + interp->local--; + + + /* If OK, and the result is a proc, add it to the list of local procs */ + if (retcode == 0) { + const char *procname = Jim_String(Jim_GetResult(interp)); + + if (Jim_FindHashEntry(&interp->commands, procname) == NULL) { + Jim_SetResultFormatted(interp, "not a proc: \"%s\"", procname); + return JIM_ERR; + } + if (interp->localProcs == NULL) { + interp->localProcs = Jim_Alloc(sizeof(*interp->localProcs)); + Jim_InitStack(interp->localProcs); + } + Jim_StackPush(interp->localProcs, Jim_StrDup(procname)); + } + + return retcode; +} + +/* [upcall] */ +static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); + return JIM_ERR; + } + else { + int retcode; + + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); + if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->u.proc.prevCmd) { + Jim_SetResultFormatted(interp, "no previous proc: \"%#s\"", argv[1]); + return JIM_ERR; + } + /* OK. Mark this command as being in an upcall */ + cmdPtr->u.proc.upcall++; + JimIncrCmdRefCount(cmdPtr); + + /* Invoke the command as normal */ + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + + /* No longer in an upcall */ + cmdPtr->u.proc.upcall--; + JimDecrCmdRefCount(interp, cmdPtr); + + return retcode; + } +} + +/* [concat] */ +static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + return JIM_OK; +} + +/* [upvar] */ +static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_CallFrame *targetCallFrame; + + /* Lookup the target frame pointer */ + if (argc > 3 && (argc % 2 == 0)) { + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + + /* Check for arity */ + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); + return JIM_ERR; + } + + /* Now... for every other/local couple: */ + for (i = 1; i < argc; i += 2) { + if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) + return JIM_ERR; + } + return JIM_OK; +} + +/* [global] */ +static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); + return JIM_ERR; + } + /* Link every var to the toplevel having the same name */ + if (interp->framePtr->level == 0) + return JIM_OK; /* global at toplevel... */ + for (i = 1; i < argc; i++) { + if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) + return JIM_ERR; + } + return JIM_OK; +} + +/* does the [string map] operation. On error NULL is returned, + * otherwise a new string object with the result, having refcount = 0, + * is returned. */ +static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr, + Jim_Obj *objPtr, int nocase) +{ + int numMaps; + const char *str, *noMatchStart = NULL; + int strLen, i; + Jim_Obj *resultObjPtr; + + numMaps = Jim_ListLength(interp, mapListObjPtr); + if (numMaps % 2) { + Jim_SetResultString(interp, "list must contain an even number of elements", -1); + return NULL; + } + + str = Jim_String(objPtr); + strLen = Jim_Utf8Length(interp, objPtr); + + /* Map it */ + resultObjPtr = Jim_NewStringObj(interp, "", 0); + while (strLen) { + for (i = 0; i < numMaps; i += 2) { + Jim_Obj *objPtr; + const char *k; + int kl; + + Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE); + k = Jim_String(objPtr); + kl = Jim_Utf8Length(interp, objPtr); + + if (strLen >= kl && kl) { + int rc; + if (nocase) { + rc = JimStringCompareNoCase(str, k, kl); + } + else { + rc = JimStringCompare(str, kl, k, kl); + } + if (rc == 0) { + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + noMatchStart = NULL; + } + Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE); + Jim_AppendObj(interp, resultObjPtr, objPtr); + str += utf8_index(str, kl); + strLen -= kl; + break; + } + } + } + if (i == numMaps) { /* no match */ + int c; + if (noMatchStart == NULL) + noMatchStart = str; + str += utf8_tounicode(str, &c); + strLen--; + } + } + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + } + return resultObjPtr; +} + +/* [string] */ +static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int len; + int opt_case = 1; + int option; + static const char * const options[] = { + "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "map", + "repeat", "reverse", "index", "first", "last", + "trim", "trimleft", "trimright", "tolower", "toupper", NULL + }; + enum + { + OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_MAP, + OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, + OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER + }; + static const char * const nocase_options[] = { + "-nocase", NULL + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) + return JIM_ERR; + + switch (option) { + case OPT_LENGTH: + case OPT_BYTELENGTH: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_LENGTH) { + len = Jim_Utf8Length(interp, argv[2]); + } + else { + len = Jim_Length(argv[2]); + } + Jim_SetResultInt(interp, len); + return JIM_OK; + + case OPT_COMPARE: + case OPT_EQUAL: + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? string1 string2"); + return JIM_ERR; + } + if (opt_case == 0) { + argv++; + } + if (option == OPT_COMPARE || !opt_case) { + Jim_SetResultInt(interp, Jim_StringCompareObj(interp, argv[2], argv[3], !opt_case)); + } + else { + Jim_SetResultBool(interp, Jim_StringEqObj(argv[2], argv[3])); + } + return JIM_OK; + + case OPT_MATCH: + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? pattern string"); + return JIM_ERR; + } + if (opt_case == 0) { + argv++; + } + Jim_SetResultBool(interp, Jim_StringMatchObj(interp, argv[2], argv[3], !opt_case)); + return JIM_OK; + + case OPT_MAP:{ + Jim_Obj *objPtr; + + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList string"); + return JIM_ERR; + } + + if (opt_case == 0) { + argv++; + } + objPtr = JimStringMap(interp, argv[2], argv[3], !opt_case); + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_RANGE: + case OPT_BYTERANGE:{ + Jim_Obj *objPtr; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "string first last"); + return JIM_ERR; + } + if (option == OPT_RANGE) { + objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); + } + else + { + objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); + } + + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REPEAT:{ + Jim_Obj *objPtr; + jim_wide count; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string count"); + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) { + return JIM_ERR; + } + objPtr = Jim_NewStringObj(interp, "", 0); + if (count > 0) { + while (count--) { + Jim_AppendObj(interp, objPtr, argv[2]); + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REVERSE:{ + char *buf, *p; + const char *str; + int len; + int i; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + + str = Jim_GetString(argv[2], &len); + buf = Jim_Alloc(len + 1); + p = buf + len; + *p = 0; + for (i = 0; i < len; ) { + int c; + int l = utf8_tounicode(str, &c); + memcpy(p - l, str, l); + p -= l; + i += l; + str += l; + } + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); + return JIM_OK; + } + + case OPT_INDEX:{ + int idx; + const char *str; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string index"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) { + return JIM_ERR; + } + str = Jim_String(argv[2]); + len = Jim_Utf8Length(interp, argv[2]); + if (idx != INT_MIN && idx != INT_MAX) { + idx = JimRelToAbsIndex(len, idx); + } + if (idx < 0 || idx >= len || str == NULL) { + Jim_SetResultString(interp, "", 0); + } + else if (len == Jim_Length(argv[2])) { + /* ASCII optimisation */ + Jim_SetResultString(interp, str + idx, 1); + } + else { + int c; + int i = utf8_index(str, idx); + Jim_SetResultString(interp, str + i, utf8_tounicode(str + i, &c)); + } + return JIM_OK; + } + + case OPT_FIRST: + case OPT_LAST:{ + int idx = 0, l1, l2; + const char *s1, *s2; + + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?"); + return JIM_ERR; + } + s1 = Jim_String(argv[2]); + s2 = Jim_String(argv[3]); + l1 = Jim_Utf8Length(interp, argv[2]); + l2 = Jim_Utf8Length(interp, argv[3]); + if (argc == 5) { + if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) { + return JIM_ERR; + } + idx = JimRelToAbsIndex(l2, idx); + } + else if (option == OPT_LAST) { + idx = l2; + } + if (option == OPT_FIRST) { + Jim_SetResultInt(interp, JimStringFirst(s1, l1, s2, l2, idx)); + } + else { +#ifdef JIM_UTF8 + Jim_SetResultInt(interp, JimStringLastUtf8(s1, l1, s2, idx)); +#else + Jim_SetResultInt(interp, JimStringLast(s1, l1, s2, idx)); +#endif + } + return JIM_OK; + } + + case OPT_TRIM: + case OPT_TRIMLEFT: + case OPT_TRIMRIGHT:{ + Jim_Obj *trimchars; + + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?"); + return JIM_ERR; + } + trimchars = (argc == 4 ? argv[3] : NULL); + if (option == OPT_TRIM) { + Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMLEFT) { + Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMRIGHT) { + Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars)); + } + return JIM_OK; + } + + case OPT_TOLOWER: + case OPT_TOUPPER: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_TOLOWER) { + Jim_SetResult(interp, JimStringToLower(interp, argv[2])); + } + else { + Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); + } + return JIM_OK; + + case OPT_IS: + if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { + return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); + } + Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); + return JIM_ERR; + } + return JIM_OK; +} + +/* [time] */ +static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long i, count = 1; + jim_wide start, elapsed; + char buf[60]; + const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration"; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "script ?count?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetLong(interp, argv[2], &count) != JIM_OK) + return JIM_ERR; + } + if (count < 0) + return JIM_OK; + i = count; + start = JimClock(); + while (i-- > 0) { + int retval; + + retval = Jim_EvalObj(interp, argv[1]); + if (retval != JIM_OK) { + return retval; + } + } + elapsed = JimClock() - start; + sprintf(buf, fmt, count == 0 ? 0 : elapsed / count); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; +} + +/* [exit] */ +static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long exitCode = 0; + + if (argc > 2) { + Jim_WrongNumArgs(interp, 1, argv, "?exitCode?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK) + return JIM_ERR; + } + interp->exitCode = exitCode; + return JIM_EXIT; +} + +/* [catch] */ +static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int exitCode = 0; + int i; + int sig = 0; + + /* Which return codes are ignored (passed through)? By default, only exit, eval and signal */ + jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); + static const int max_ignore_code = sizeof(ignore_mask) * 8; + + /* Reset the error code before catch. + * Note that this is not strictly correct. + */ + Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); + + for (i = 1; i < argc - 1; i++) { + const char *arg = Jim_String(argv[i]); + jim_wide option; + int ignore; + + /* It's a pity we can't use Jim_GetEnum here :-( */ + if (strcmp(arg, "--") == 0) { + i++; + break; + } + if (*arg != '-') { + break; + } + + if (strncmp(arg, "-no", 3) == 0) { + arg += 3; + ignore = 1; + } + else { + arg++; + ignore = 0; + } + + if (Jim_StringToWide(arg, &option, 10) != JIM_OK) { + option = -1; + } + if (option < 0) { + option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize); + } + if (option < 0) { + goto wrongargs; + } + + if (ignore) { + ignore_mask |= (1 << option); + } + else { + ignore_mask &= ~(1 << option); + } + } + + argc -= i; + if (argc < 1 || argc > 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-?no?code ... --? script ?resultVarName? ?optionVarName?"); + return JIM_ERR; + } + argv += i; + + if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { + sig++; + } + + interp->signal_level += sig; + if (interp->signal_level && interp->sigmask) { + /* If a signal is set, don't even try to execute the body */ + exitCode = JIM_SIGNAL; + } + else { + exitCode = Jim_EvalObj(interp, argv[0]); + } + interp->signal_level -= sig; + + /* Catch or pass through? Only the first 32/64 codes can be passed through */ + if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) { + /* Not caught, pass it up */ + return exitCode; + } + + if (sig && exitCode == JIM_SIGNAL) { + /* Catch the signal at this level */ + if (interp->signal_set_result) { + interp->signal_set_result(interp, interp->sigmask); + } + else { + Jim_SetResultInt(interp, interp->sigmask); + } + interp->sigmask = 0; + } + + if (argc >= 2) { + if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) { + return JIM_ERR; + } + if (argc == 3) { + Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); + Jim_ListAppendElement(interp, optListObj, + Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); + Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); + if (exitCode == JIM_ERR) { + Jim_Obj *errorCode; + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", + -1)); + Jim_ListAppendElement(interp, optListObj, interp->stackTrace); + + errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); + if (errorCode) { + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); + Jim_ListAppendElement(interp, optListObj, errorCode); + } + } + if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) { + return JIM_ERR; + } + } + } + Jim_SetResultInt(interp, exitCode); + return JIM_OK; +} + +#ifdef JIM_REFERENCES + +/* [ref] */ +static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); + return JIM_ERR; + } + if (argc == 3) { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); + } + else { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); + } + return JIM_OK; +} + +/* [getref] */ +static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "reference"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, refPtr->objPtr); + return JIM_OK; +} + +/* [setref] */ +static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_IncrRefCount(argv[2]); + Jim_DecrRefCount(interp, refPtr->objPtr); + refPtr->objPtr = argv[2]; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + +/* [collect] */ +static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_Collect(interp)); + + /* Free all the freed objects. */ + while (interp->freeList) { + Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; + Jim_Free(interp->freeList); + interp->freeList = nextObjPtr; + } + + return JIM_OK; +} + +/* [finalize] reference ?newValue? */ +static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *cmdNamePtr; + + if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) + return JIM_ERR; + if (cmdNamePtr != NULL) /* otherwise the null string is returned. */ + Jim_SetResult(interp, cmdNamePtr); + } + else { + if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + } + return JIM_OK; +} + +/* [info references] */ +static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + + listObjPtr = Jim_NewListObj(interp, NULL, 0); + + htiter = Jim_GetHashTableIterator(&interp->references); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + char buf[JIM_REFERENCE_SPACE]; + Jim_Reference *refPtr = he->u.val; + const jim_wide *refId = he->key; + + JimFormatReference(buf, refPtr, *refId); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); + } + Jim_FreeHashTableIterator(htiter); + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} +#endif + +/* [rename] */ +static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *oldName, *newName; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "oldName newName"); + return JIM_ERR; + } + + if (JimValidName(interp, "new procedure", argv[2])) { + return JIM_ERR; + } + + oldName = Jim_String(argv[1]); + newName = Jim_String(argv[2]); + return Jim_RenameCommand(interp, oldName, newName); +} + +int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + /* XXX: Could make the exact-match case much more efficient here. + * See JimCommandsList() + */ + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetResult(interp, resultObj); + return JIM_OK; +} + +int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return -1; + } + return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; +} + +/* [dict] */ +static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int option; + static const char * const options[] = { + "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL + }; + enum + { + OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH, + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); + return JIM_ERR; + } + + if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + switch (option) { + case OPT_GET: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); + return JIM_ERR; + } + if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, + JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + + case OPT_SET: + if (argc < 5) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); + return JIM_ERR; + } + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); + + case OPT_EXIST: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); + return JIM_ERR; + } + Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, + &objPtr, JIM_ERRMSG) == JIM_OK); + return JIM_OK; + + case OPT_UNSET: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); + return JIM_ERR; + } + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE); + + case OPT_KEYS: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?"); + return JIM_ERR; + } + return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); + + case OPT_SIZE: { + int size; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar"); + return JIM_ERR; + } + + size = Jim_DictSize(interp, argv[2]); + if (size < 0) { + return JIM_ERR; + } + Jim_SetResultInt(interp, size); + return JIM_OK; + } + + case OPT_MERGE: + if (argc == 2) { + return JIM_OK; + } + else if (argv[2]->typePtr != &dictObjType && SetDictFromAny(interp, argv[2]) != JIM_OK) { + return JIM_ERR; + } + else { + return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2); + } + + case OPT_WITH: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); + return JIM_ERR; + } + else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) { + return JIM_ERR; + } + else { + return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2); + } + + case OPT_CREATE: + if (argc % 2) { + Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); + return JIM_ERR; + } + objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); + Jim_SetResult(interp, objPtr); + return JIM_OK; + + default: + abort(); + } +} + +/* [subst] */ +static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-nobackslashes", "-nocommands", "-novariables", NULL + }; + enum + { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES }; + int i; + int flags = JIM_SUBST_FLAG; + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? string"); + return JIM_ERR; + } + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NOBACKSLASHES: + flags |= JIM_SUBST_NOESC; + break; + case OPT_NOCOMMANDS: + flags |= JIM_SUBST_NOCMD; + break; + case OPT_NOVARIABLES: + flags |= JIM_SUBST_NOVAR; + break; + } + } + if (Jim_SubstObj(interp, argv[argc - 1], &objPtr, flags) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [info] */ +static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int cmd; + Jim_Obj *objPtr; + int mode = 0; + + static const char * const commands[] = { + "body", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals", + "vars", "version", "patchlevel", "complete", "args", "hostname", + "script", "source", "stacktrace", "nameofexecutable", "returncodes", + "references", NULL + }; + enum + { INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, + INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, + INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, + INFO_RETURNCODES, INFO_REFERENCES, + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) + != JIM_OK) { + return JIM_ERR; + } + + /* Test for the the most common commands first, just in case it makes a difference */ + switch (cmd) { + case INFO_EXISTS:{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName"); + return JIM_ERR; + } + Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL); + break; + } + + case INFO_CHANNELS: +#ifndef jim_ext_aio + Jim_SetResultString(interp, "aio not enabled", -1); + return JIM_ERR; +#endif + case INFO_COMMANDS: + case INFO_PROCS: + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } + Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, + (cmd - INFO_COMMANDS))); + break; + + case INFO_VARS: + mode++; /* JIM_VARLIST_VARS */ + case INFO_LOCALS: + mode++; /* JIM_VARLIST_LOCALS */ + case INFO_GLOBALS: + /* mode 0 => JIM_VARLIST_GLOBALS */ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } + Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode)); + break; + + case INFO_SCRIPT: + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileNameObj); + break; + + case INFO_SOURCE:{ + int line; + Jim_Obj *resObjPtr; + Jim_Obj *fileNameObj; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "source"); + return JIM_ERR; + } + if (argv[2]->typePtr == &sourceObjType) { + fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj; + line = argv[2]->internalRep.sourceValue.lineNumber; + } + else if (argv[2]->typePtr == &scriptObjType) { + ScriptObj *script = Jim_GetScript(interp, argv[2]); + fileNameObj = script->fileNameObj; + line = script->line; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + resObjPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, resObjPtr, fileNameObj); + Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); + Jim_SetResult(interp, resObjPtr); + break; + } + + case INFO_STACKTRACE: + Jim_SetResult(interp, interp->stackTrace); + break; + + case INFO_LEVEL: + case INFO_FRAME: + switch (argc) { + case 2: + Jim_SetResultInt(interp, interp->framePtr->level); + break; + + case 3: + if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + break; + + default: + Jim_WrongNumArgs(interp, 2, argv, "?levelNum?"); + return JIM_ERR; + } + break; + + case INFO_BODY: + case INFO_ARGS:{ + Jim_Cmd *cmdPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "procname"); + return JIM_ERR; + } + if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { + return JIM_ERR; + } + if (!cmdPtr->isproc) { + Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]); + return JIM_ERR; + } + Jim_SetResult(interp, + cmd == INFO_BODY ? cmdPtr->u.proc.bodyObjPtr : cmdPtr->u.proc.argListObjPtr); + break; + } + + case INFO_VERSION: + case INFO_PATCHLEVEL:{ + char buf[(JIM_INTEGER_SPACE * 2) + 1]; + + sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetResultString(interp, buf, -1); + break; + } + + case INFO_COMPLETE: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "script ?missing?"); + return JIM_ERR; + } + else { + int len; + const char *s = Jim_GetString(argv[2], &len); + char missing; + + Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing)); + if (missing != ' ' && argc == 4) { + Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1)); + } + } + break; + + case INFO_HOSTNAME: + /* Redirect to os.gethostname if it exists */ + return Jim_Eval(interp, "os.gethostname"); + + case INFO_NAMEOFEXECUTABLE: + /* Redirect to Tcl proc */ + return Jim_Eval(interp, "{info nameofexecutable}"); + + case INFO_RETURNCODES: + if (argc == 2) { + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; jimReturnCodes[i]; i++) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewIntObj(interp, i)); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, + jimReturnCodes[i], -1)); + } + + Jim_SetResult(interp, listObjPtr); + } + else if (argc == 3) { + long code; + const char *name; + + if (Jim_GetLong(interp, argv[2], &code) != JIM_OK) { + return JIM_ERR; + } + name = Jim_ReturnCode(code); + if (*name == '?') { + Jim_SetResultInt(interp, code); + } + else { + Jim_SetResultString(interp, name, -1); + } + } + else { + Jim_WrongNumArgs(interp, 2, argv, "?code?"); + return JIM_ERR; + } + break; + case INFO_REFERENCES: +#ifdef JIM_REFERENCES + return JimInfoReferences(interp, argc, argv); +#else + Jim_SetResultString(interp, "not supported", -1); + return JIM_ERR; +#endif + } + return JIM_OK; +} + +/* [exists] */ +static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + static const char * const options[] = { + "-command", "-proc", "-var", NULL + }; + enum + { + OPT_COMMAND, OPT_PROC, OPT_VAR + }; + int option; + + if (argc == 2) { + option = OPT_VAR; + objPtr = argv[1]; + } + else if (argc == 3) { + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + objPtr = argv[2]; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?option? name"); + return JIM_ERR; + } + + /* Test for the the most common commands first, just in case it makes a difference */ + switch (option) { + case OPT_VAR: + Jim_SetResultBool(interp, Jim_GetVariable(interp, objPtr, 0) != NULL); + break; + + case OPT_COMMAND: + case OPT_PROC: { + Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); + Jim_SetResultBool(interp, cmd != NULL && (option == OPT_COMMAND || cmd->isproc)); + break; + } + } + return JIM_OK; +} + +/* [split] */ +static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *str, *splitChars, *noMatchStart; + int splitLen, strLen; + Jim_Obj *resObjPtr; + int c; + int len; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?"); + return JIM_ERR; + } + + str = Jim_GetString(argv[1], &len); + if (len == 0) { + return JIM_OK; + } + strLen = Jim_Utf8Length(interp, argv[1]); + + /* Init */ + if (argc == 2) { + splitChars = " \n\t\r"; + splitLen = 4; + } + else { + splitChars = Jim_String(argv[2]); + splitLen = Jim_Utf8Length(interp, argv[2]); + } + + noMatchStart = str; + resObjPtr = Jim_NewListObj(interp, NULL, 0); + + /* Split */ + if (splitLen) { + Jim_Obj *objPtr; + while (strLen--) { + const char *sc = splitChars; + int scLen = splitLen; + int sl = utf8_tounicode(str, &c); + while (scLen--) { + int pc; + sc += utf8_tounicode(sc, &pc); + if (c == pc) { + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + noMatchStart = str + sl; + break; + } + } + str += sl; + } + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + } + else { + /* This handles the special case of splitchars eq {} + * Optimise by sharing common (ASCII) characters + */ + Jim_Obj **commonObj = NULL; +#define NUM_COMMON (128 - 9) + while (strLen--) { + int n = utf8_tounicode(str, &c); +#ifdef JIM_OPTIMIZATION + if (c >= 9 && c < 128) { + /* Common ASCII char. Note that 9 is the tab character */ + c -= 9; + if (!commonObj) { + commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); + memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); + } + if (!commonObj[c]) { + commonObj[c] = Jim_NewStringObj(interp, str, 1); + } + Jim_ListAppendElement(interp, resObjPtr, commonObj[c]); + str++; + continue; + } +#endif + Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObjUtf8(interp, str, 1)); + str += n; + } + Jim_Free(commonObj); + } + + Jim_SetResult(interp, resObjPtr); + return JIM_OK; +} + +/* [join] */ +static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *joinStr; + int joinStrLen, i, listLen; + Jim_Obj *resObjPtr; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); + return JIM_ERR; + } + /* Init */ + if (argc == 2) { + joinStr = " "; + joinStrLen = 1; + } + else { + joinStr = Jim_GetString(argv[2], &joinStrLen); + } + listLen = Jim_ListLength(interp, argv[1]); + resObjPtr = Jim_NewStringObj(interp, NULL, 0); + /* Split */ + for (i = 0; i < listLen; i++) { + Jim_Obj *objPtr = 0; + + Jim_ListIndex(interp, argv[1], i, &objPtr, JIM_NONE); + Jim_AppendObj(interp, resObjPtr, objPtr); + if (i + 1 != listLen) { + Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); + } + } + Jim_SetResult(interp, resObjPtr); + return JIM_OK; +} + +/* [format] */ +static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?"); + return JIM_ERR; + } + objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2); + if (objPtr == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [scan] */ +static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listPtr, **outVec; + int outc, i; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?"); + return JIM_ERR; + } + if (argv[2]->typePtr != &scanFmtStringObjType) + SetScanFmtFromAny(interp, argv[2]); + if (FormatGetError(argv[2]) != 0) { + Jim_SetResultString(interp, FormatGetError(argv[2]), -1); + return JIM_ERR; + } + if (argc > 3) { + int maxPos = FormatGetMaxPos(argv[2]); + int count = FormatGetCnvCount(argv[2]); + + if (maxPos > argc - 3) { + Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1); + return JIM_ERR; + } + else if (count > argc - 3) { + Jim_SetResultString(interp, "different numbers of variable names and " + "field specifiers", -1); + return JIM_ERR; + } + else if (count < argc - 3) { + Jim_SetResultString(interp, "variable is not assigned by any " + "conversion specifiers", -1); + return JIM_ERR; + } + } + listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG); + if (listPtr == 0) + return JIM_ERR; + if (argc > 3) { + int rc = JIM_OK; + int count = 0; + + if (listPtr != 0 && listPtr != (Jim_Obj *)EOF) { + int len = Jim_ListLength(interp, listPtr); + + if (len != 0) { + JimListGetElements(interp, listPtr, &outc, &outVec); + for (i = 0; i < outc; ++i) { + if (Jim_Length(outVec[i]) > 0) { + ++count; + if (Jim_SetVariable(interp, argv[3 + i], outVec[i]) != JIM_OK) { + rc = JIM_ERR; + } + } + } + } + Jim_FreeNewObj(interp, listPtr); + } + else { + count = -1; + } + if (rc == JIM_OK) { + Jim_SetResultInt(interp, count); + } + return rc; + } + else { + if (listPtr == (Jim_Obj *)EOF) { + Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0)); + return JIM_OK; + } + Jim_SetResult(interp, listPtr); + } + return JIM_OK; +} + +/* [error] */ +static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?"); + return JIM_ERR; + } + Jim_SetResult(interp, argv[1]); + if (argc == 3) { + JimSetStackTrace(interp, argv[2]); + return JIM_ERR; + } + interp->addStackTrace++; + return JIM_ERR; +} + +/* [lrange] */ +static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last"); + return JIM_ERR; + } + if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [lrepeat] */ +static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + long count; + + if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) { + Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?"); + return JIM_ERR; + } + + if (count == 0 || argc == 2) { + return JIM_OK; + } + + argc -= 2; + argv += 2; + + objPtr = Jim_NewListObj(interp, argv, argc); + while (--count) { + int i; + + for (i = 0; i < argc; i++) { + ListAppendElement(objPtr, argv[i]); + } + } + + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +char **Jim_GetEnviron(void) +{ +#if defined(HAVE__NSGETENVIRON) + return *_NSGetEnviron(); +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + return environ; +#endif +} + +void Jim_SetEnviron(char **env) +{ +#if defined(HAVE__NSGETENVIRON) + *_NSGetEnviron() = env; +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + environ = env; +#endif +} + +/* [env] */ +static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *key; + const char *val; + + if (argc == 1) { + char **e = Jim_GetEnviron(); + + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; e[i]; i++) { + const char *equals = strchr(e[i], '='); + + if (equals) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, e[i], + equals - e[i])); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1)); + } + } + + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?default?"); + return JIM_ERR; + } + key = Jim_String(argv[1]); + val = getenv(key); + if (val == NULL) { + if (argc < 3) { + Jim_SetResultFormatted(interp, "environment variable \"%#s\" does not exist", argv[1]); + return JIM_ERR; + } + val = Jim_String(argv[2]); + } + Jim_SetResult(interp, Jim_NewStringObj(interp, val, -1)); + return JIM_OK; +} + +/* [source] */ +static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "fileName"); + return JIM_ERR; + } + retval = Jim_EvalFile(interp, Jim_String(argv[1])); + if (retval == JIM_RETURN) + return JIM_OK; + return retval; +} + +/* [lreverse] */ +static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *revObjPtr, **ele; + int len; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + JimListGetElements(interp, argv[1], &len, &ele); + len--; + revObjPtr = Jim_NewListObj(interp, NULL, 0); + while (len >= 0) + ListAppendElement(revObjPtr, ele[len--]); + Jim_SetResult(interp, revObjPtr); + return JIM_OK; +} + +static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step) +{ + jim_wide len; + + if (step == 0) + return -1; + if (start == end) + return 0; + else if (step > 0 && start > end) + return -1; + else if (step < 0 && end > start) + return -1; + len = end - start; + if (len < 0) + len = -len; /* abs(len) */ + if (step < 0) + step = -step; /* abs(step) */ + len = 1 + ((len - 1) / step); + /* We can truncate safely to INT_MAX, the range command + * will always return an error for a such long range + * because Tcl lists can't be so long. */ + if (len > INT_MAX) + len = INT_MAX; + return (int)((len < 0) ? -1 : len); +} + +/* [range] */ +static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide start = 0, end, step = 1; + int len, i; + Jim_Obj *objPtr; + + if (argc < 2 || argc > 4) { + Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &end) != JIM_OK) + return JIM_ERR; + } + else { + if (Jim_GetWide(interp, argv[1], &start) != JIM_OK || + Jim_GetWide(interp, argv[2], &end) != JIM_OK) + return JIM_ERR; + if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK) + return JIM_ERR; + } + if ((len = JimRangeLen(start, end, step)) == -1) { + Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1); + return JIM_ERR; + } + objPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < len; i++) + ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step)); + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [rand] */ +static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide min = 0, max = 0, len, maxMul; + + if (argc < 1 || argc > 3) { + Jim_WrongNumArgs(interp, 1, argv, "?min? max"); + return JIM_ERR; + } + if (argc == 1) { + max = JIM_WIDE_MAX; + } else if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &max) != JIM_OK) + return JIM_ERR; + } else if (argc == 3) { + if (Jim_GetWide(interp, argv[1], &min) != JIM_OK || + Jim_GetWide(interp, argv[2], &max) != JIM_OK) + return JIM_ERR; + } + len = max-min; + if (len < 0) { + Jim_SetResultString(interp, "Invalid arguments (max < min)", -1); + return JIM_ERR; + } + maxMul = JIM_WIDE_MAX - (len ? (JIM_WIDE_MAX%len) : 0); + while (1) { + jim_wide r; + + JimRandomBytes(interp, &r, sizeof(jim_wide)); + if (r < 0 || r >= maxMul) continue; + r = (len == 0) ? 0 : r%len; + Jim_SetResultInt(interp, min+r); + return JIM_OK; + } +} + +static const struct { + const char *name; + Jim_CmdProc cmdProc; +} Jim_CoreCommandsTable[] = { + {"set", Jim_SetCoreCommand}, + {"unset", Jim_UnsetCoreCommand}, + {"puts", Jim_PutsCoreCommand}, + {"+", Jim_AddCoreCommand}, + {"*", Jim_MulCoreCommand}, + {"-", Jim_SubCoreCommand}, + {"/", Jim_DivCoreCommand}, + {"incr", Jim_IncrCoreCommand}, + {"while", Jim_WhileCoreCommand}, + {"loop", Jim_LoopCoreCommand}, + {"for", Jim_ForCoreCommand}, + {"foreach", Jim_ForeachCoreCommand}, + {"lmap", Jim_LmapCoreCommand}, + {"if", Jim_IfCoreCommand}, + {"switch", Jim_SwitchCoreCommand}, + {"list", Jim_ListCoreCommand}, + {"lindex", Jim_LindexCoreCommand}, + {"lset", Jim_LsetCoreCommand}, + {"lsearch", Jim_LsearchCoreCommand}, + {"llength", Jim_LlengthCoreCommand}, + {"lappend", Jim_LappendCoreCommand}, + {"linsert", Jim_LinsertCoreCommand}, + {"lreplace", Jim_LreplaceCoreCommand}, + {"lsort", Jim_LsortCoreCommand}, + {"append", Jim_AppendCoreCommand}, + {"debug", Jim_DebugCoreCommand}, + {"eval", Jim_EvalCoreCommand}, + {"uplevel", Jim_UplevelCoreCommand}, + {"expr", Jim_ExprCoreCommand}, + {"break", Jim_BreakCoreCommand}, + {"continue", Jim_ContinueCoreCommand}, + {"proc", Jim_ProcCoreCommand}, + {"concat", Jim_ConcatCoreCommand}, + {"return", Jim_ReturnCoreCommand}, + {"upvar", Jim_UpvarCoreCommand}, + {"global", Jim_GlobalCoreCommand}, + {"string", Jim_StringCoreCommand}, + {"time", Jim_TimeCoreCommand}, + {"exit", Jim_ExitCoreCommand}, + {"catch", Jim_CatchCoreCommand}, +#ifdef JIM_REFERENCES + {"ref", Jim_RefCoreCommand}, + {"getref", Jim_GetrefCoreCommand}, + {"setref", Jim_SetrefCoreCommand}, + {"finalize", Jim_FinalizeCoreCommand}, + {"collect", Jim_CollectCoreCommand}, +#endif + {"rename", Jim_RenameCoreCommand}, + {"dict", Jim_DictCoreCommand}, + {"subst", Jim_SubstCoreCommand}, + {"info", Jim_InfoCoreCommand}, + {"exists", Jim_ExistsCoreCommand}, + {"split", Jim_SplitCoreCommand}, + {"join", Jim_JoinCoreCommand}, + {"format", Jim_FormatCoreCommand}, + {"scan", Jim_ScanCoreCommand}, + {"error", Jim_ErrorCoreCommand}, + {"lrange", Jim_LrangeCoreCommand}, + {"lrepeat", Jim_LrepeatCoreCommand}, + {"env", Jim_EnvCoreCommand}, + {"source", Jim_SourceCoreCommand}, + {"lreverse", Jim_LreverseCoreCommand}, + {"range", Jim_RangeCoreCommand}, + {"rand", Jim_RandCoreCommand}, + {"tailcall", Jim_TailcallCoreCommand}, + {"local", Jim_LocalCoreCommand}, + {"upcall", Jim_UpcallCoreCommand}, + {NULL, NULL}, +}; + +void Jim_RegisterCoreCommands(Jim_Interp *interp) +{ + int i = 0; + + while (Jim_CoreCommandsTable[i].name != NULL) { + Jim_CreateCommand(interp, + Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL); + i++; + } +} + +/* ----------------------------------------------------------------------------- + * Interactive prompt + * ---------------------------------------------------------------------------*/ +void Jim_MakeErrorMessage(Jim_Interp *interp) +{ + Jim_Obj *argv[2]; + + argv[0] = Jim_NewStringObj(interp, "errorInfo", -1); + argv[1] = interp->result; + + Jim_EvalObjVector(interp, 2, argv); +} + +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name) +{ + int count; + char **tablePtrSorted; + int i; + + for (count = 0; tablePtr[count]; count++) { + } + + if (name == NULL) { + name = "option"; + } + + Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); + tablePtrSorted = Jim_Alloc(sizeof(char *) * count); + memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); + qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); + for (i = 0; i < count; i++) { + if (i + 1 == count && count > 1) { + Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); + if (i + 1 != count) { + Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); + } + } + Jim_Free(tablePtrSorted); +} + +int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, + const char *const *tablePtr, int *indexPtr, const char *name, int flags) +{ + const char *bad = "bad "; + const char *const *entryPtr = NULL; + int i; + int match = -1; + int arglen; + const char *arg = Jim_GetString(objPtr, &arglen); + + *indexPtr = -1; + + for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { + if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { + /* Found an exact match */ + *indexPtr = i; + return JIM_OK; + } + if (flags & JIM_ENUM_ABBREV) { + /* Accept an unambiguous abbreviation. + * Note that '-' doesnt' consitute a valid abbreviation + */ + if (strncmp(arg, *entryPtr, arglen) == 0) { + if (*arg == '-' && arglen == 1) { + break; + } + if (match >= 0) { + bad = "ambiguous "; + goto ambiguous; + } + match = i; + } + } + } + + /* If we had an unambiguous partial match */ + if (match >= 0) { + *indexPtr = match; + return JIM_OK; + } + + ambiguous: + if (flags & JIM_ERRMSG) { + JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name); + } + return JIM_ERR; +} + +int Jim_FindByName(const char *name, const char * const array[], size_t len) +{ + int i; + + for (i = 0; i < (int)len; i++) { + if (array[i] && strcmp(array[i], name) == 0) { + return i; + } + } + return -1; +} + +int Jim_IsDict(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &dictObjType; +} + +int Jim_IsList(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &listObjType; +} + +/** + * Very simple printf-like formatting, designed for error messages. + * + * The format may contain up to 5 '%s' or '%#s', corresponding to variable arguments. + * The resulting string is created and set as the result. + * + * Each '%s' should correspond to a regular string parameter. + * Each '%#s' should correspond to a (Jim_Obj *) parameter. + * Any other printf specifier is not allowed (but %% is allowed for the % character). + * + * e.g. Jim_SetResultFormatted(interp, "Bad option \"%#s\" in proc \"%#s\"", optionObjPtr, procNamePtr); + * + * Note: We take advantage of the fact that printf has the same behaviour for both %s and %#s + */ +void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) +{ + /* Initial space needed */ + int len = strlen(format); + int extra = 0; + int n = 0; + const char *params[5]; + char *buf; + va_list args; + int i; + + va_start(args, format); + + for (i = 0; i < len && n < 5; i++) { + int l; + + if (strncmp(format + i, "%s", 2) == 0) { + params[n] = va_arg(args, char *); + + l = strlen(params[n]); + } + else if (strncmp(format + i, "%#s", 3) == 0) { + Jim_Obj *objPtr = va_arg(args, Jim_Obj *); + + params[n] = Jim_GetString(objPtr, &l); + } + else { + if (format[i] == '%') { + i++; + } + continue; + } + n++; + extra += l; + } + + len += extra; + buf = Jim_Alloc(len + 1); + len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); +} + +/* stubs */ +#ifndef jim_ext_package +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) +{ + return JIM_OK; +} +#endif +#ifndef jim_ext_aio +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) +{ + Jim_SetResultString(interp, "aio not enabled", -1); + return NULL; +} +#endif + + +/* + * Local Variables: *** + * c-basic-offset: 4 *** + * tab-width: 4 *** + * End: *** + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jim.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jim.h new file mode 100755 index 0000000..fdc9db9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jim.h @@ -0,0 +1,917 @@ +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + *--- Inline Header File Documentation --- + * [By Duane Ellis, openocd@duaneellis.com, 8/18/8] + * + * Belief is "Jim" would greatly benifit if Jim Internals where + * documented in some way - form whatever, and perhaps - the package: + * 'doxygen' is the correct approach to do that. + * + * Details, see: http://www.stack.nl/~dimitri/doxygen/ + * + * To that end please follow these guide lines: + * + * (A) Document the PUBLIC api in the .H file. + * + * (B) Document JIM Internals, in the .C file. + * + * (C) Remember JIM is embedded in other packages, to that end do + * not assume that your way of documenting is the right way, Jim's + * public documentation should be agnostic, such that it is some + * what agreeable with the "package" that is embedding JIM inside + * of it's own doxygen documentation. + * + * (D) Use minimal Doxygen tags. + * + * This will be an "ongoing work in progress" for some time. + **/ + +#ifndef __JIM__H +#define __JIM__H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <time.h> +#include <limits.h> +#include <stdio.h> /* for the FILE typedef definition */ +#include <stdlib.h> /* In order to export the Jim_Free() macro */ +#include <stdarg.h> /* In order to get type va_list */ + +/* ----------------------------------------------------------------------------- + * System configuration + * autoconf (configure) will set these + * ---------------------------------------------------------------------------*/ +#include <jim-win32compat.h> + +#ifndef HAVE_NO_AUTOCONF +#include <jim-config.h> +#endif + +/* ----------------------------------------------------------------------------- + * Compiler specific fixes. + * ---------------------------------------------------------------------------*/ + +/* Long Long type and related issues */ +#ifndef jim_wide +# ifdef HAVE_LONG_LONG +# define jim_wide long long +# ifndef LLONG_MAX +# define LLONG_MAX 9223372036854775807LL +# endif +# ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# endif +# define JIM_WIDE_MIN LLONG_MIN +# define JIM_WIDE_MAX LLONG_MAX +# else +# define jim_wide long +# define JIM_WIDE_MIN LONG_MIN +# define JIM_WIDE_MAX LONG_MAX +# endif + +/* ----------------------------------------------------------------------------- + * LIBC specific fixes + * ---------------------------------------------------------------------------*/ + +# ifdef HAVE_LONG_LONG +# define JIM_WIDE_MODIFIER "lld" +# else +# define JIM_WIDE_MODIFIER "ld" +# define strtoull strtoul +# endif +#endif + +#define UCHAR(c) ((unsigned char)(c)) + +/* ----------------------------------------------------------------------------- + * Exported defines + * ---------------------------------------------------------------------------*/ + +/* Jim version numbering: every version of jim is marked with a + * successive integer number. This is version 0. The first + * stable version will be 1, then 2, 3, and so on. */ +#define JIM_VERSION 72 + +#define JIM_OK 0 +#define JIM_ERR 1 +#define JIM_RETURN 2 +#define JIM_BREAK 3 +#define JIM_CONTINUE 4 +#define JIM_SIGNAL 5 +#define JIM_EXIT 6 +/* The following are internal codes and should never been seen/used */ +#define JIM_EVAL 7 + +#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */ + +/* Some function get an integer argument with flags to change + * the behaviour. */ +#define JIM_NONE 0 /* no flags set */ +#define JIM_ERRMSG 1 /* set an error message in the interpreter. */ + +#define JIM_UNSHARED 4 /* Flag to Jim_GetVariable() */ + +/* Flags for Jim_SubstObj() */ +#define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */ +#define JIM_SUBST_NOCMD 2 /* don't perform command substitutions */ +#define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */ +#define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */ + +/* Unused arguments generate annoying warnings... */ +#define JIM_NOTUSED(V) ((void) V) + +/* Flags for Jim_GetEnum() */ +#define JIM_ENUM_ABBREV 2 /* Allow unambiguous abbreviation */ + +/* Flags used by API calls getting a 'nocase' argument. */ +#define JIM_CASESENS 0 /* case sensitive */ +#define JIM_NOCASE 1 /* no case */ + +/* Filesystem related */ +#define JIM_PATH_LEN 1024 + +/* Newline, some embedded system may need -DJIM_CRLF */ +#ifdef JIM_CRLF +#define JIM_NL "\r\n" +#else +#define JIM_NL "\n" +#endif + +#define JIM_LIBPATH "auto_path" +#define JIM_INTERACTIVE "tcl_interactive" + +/* ----------------------------------------------------------------------------- + * Stack + * ---------------------------------------------------------------------------*/ + +typedef struct Jim_Stack { + int len; + int maxlen; + void **vector; +} Jim_Stack; + +/* ----------------------------------------------------------------------------- + * Hash table + * ---------------------------------------------------------------------------*/ + +typedef struct Jim_HashEntry { + const void *key; + union { + void *val; + int intval; + } u; + struct Jim_HashEntry *next; +} Jim_HashEntry; + +typedef struct Jim_HashTableType { + unsigned int (*hashFunction)(const void *key); + const void *(*keyDup)(void *privdata, const void *key); + void *(*valDup)(void *privdata, const void *obj); + int (*keyCompare)(void *privdata, const void *key1, const void *key2); + void (*keyDestructor)(void *privdata, const void *key); + void (*valDestructor)(void *privdata, void *obj); +} Jim_HashTableType; + +typedef struct Jim_HashTable { + Jim_HashEntry **table; + const Jim_HashTableType *type; + unsigned int size; + unsigned int sizemask; + unsigned int used; + unsigned int collisions; + void *privdata; +} Jim_HashTable; + +typedef struct Jim_HashTableIterator { + Jim_HashTable *ht; + int index; + Jim_HashEntry *entry, *nextEntry; +} Jim_HashTableIterator; + +/* This is the initial size of every hash table */ +#define JIM_HT_INITIAL_SIZE 16 + +/* ------------------------------- Macros ------------------------------------*/ +#define Jim_FreeEntryVal(ht, entry) \ + if ((ht)->type->valDestructor) \ + (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) + +#define Jim_SetHashVal(ht, entry, _val_) do { \ + if ((ht)->type->valDup) \ + entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ + else \ + entry->u.val = (_val_); \ +} while(0) + +#define Jim_FreeEntryKey(ht, entry) \ + if ((ht)->type->keyDestructor) \ + (ht)->type->keyDestructor((ht)->privdata, (entry)->key) + +#define Jim_SetHashKey(ht, entry, _key_) do { \ + if ((ht)->type->keyDup) \ + entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ + else \ + entry->key = (_key_); \ +} while(0) + +#define Jim_CompareHashKeys(ht, key1, key2) \ + (((ht)->type->keyCompare) ? \ + (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ + (key1) == (key2)) + +#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) + +#define Jim_GetHashEntryKey(he) ((he)->key) +#define Jim_GetHashEntryVal(he) ((he)->val) +#define Jim_GetHashTableCollisions(ht) ((ht)->collisions) +#define Jim_GetHashTableSize(ht) ((ht)->size) +#define Jim_GetHashTableUsed(ht) ((ht)->used) + +/* ----------------------------------------------------------------------------- + * Jim_Obj structure + * ---------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------------------------- + * Jim object. This is mostly the same as Tcl_Obj itself, + * with the addition of the 'prev' and 'next' pointers. + * In Jim all the objects are stored into a linked list for GC purposes, + * so that it's possible to access every object living in a given interpreter + * sequentially. When an object is freed, it's moved into a different + * linked list, used as object pool. + * + * The refcount of a freed object is always -1. + * ---------------------------------------------------------------------------*/ +typedef struct Jim_Obj { + int refCount; /* reference count */ + char *bytes; /* string representation buffer. NULL = no string repr. */ + int length; /* number of bytes in 'bytes', not including the numterm. */ + const struct Jim_ObjType *typePtr; /* object type. */ + /* Internal representation union */ + union { + /* integer number type */ + jim_wide wideValue; + /* hashed object type value */ + int hashValue; + /* index type */ + int indexValue; + /* return code type */ + int returnCode; + /* double number type */ + double doubleValue; + /* Generic pointer */ + void *ptr; + /* Generic two pointers value */ + struct { + void *ptr1; + void *ptr2; + } twoPtrValue; + /* Variable object */ + struct { + unsigned jim_wide callFrameId; + struct Jim_Var *varPtr; + } varValue; + /* Command object */ + struct { + unsigned jim_wide procEpoch; + struct Jim_Cmd *cmdPtr; + } cmdValue; + /* List object */ + struct { + struct Jim_Obj **ele; /* Elements vector */ + int len; /* Length */ + int maxLen; /* Allocated 'ele' length */ + } listValue; + /* String type */ + struct { + int maxLength; + int charLength; /* utf-8 char length. -1 if unknown */ + } strValue; + /* Reference type */ + struct { + jim_wide id; + struct Jim_Reference *refPtr; + } refValue; + /* Source type */ + struct { + struct Jim_Obj *fileNameObj; + int lineNumber; + } sourceValue; + /* Dict substitution type */ + struct { + struct Jim_Obj *varNameObjPtr; + struct Jim_Obj *indexObjPtr; + } dictSubstValue; + /* tagged binary type */ + struct { + unsigned char *data; + size_t len; + } binaryValue; + /* Regular expression pattern */ + struct { + unsigned flags; + void *compre; /* really an allocated (regex_t *) */ + } regexpValue; + struct { + int line; + int argc; + } scriptLineValue; + } internalRep; + /* This are 8 or 16 bytes more for every object + * but this is required for efficient garbage collection + * of Jim references. */ + struct Jim_Obj *prevObjPtr; /* pointer to the prev object. */ + struct Jim_Obj *nextObjPtr; /* pointer to the next object. */ +} Jim_Obj; + +/* Jim_Obj related macros */ +#define Jim_IncrRefCount(objPtr) \ + ++(objPtr)->refCount +#define Jim_DecrRefCount(interp, objPtr) \ + if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr) +#define Jim_IsShared(objPtr) \ + ((objPtr)->refCount > 1) + +/* This macro is used when we allocate a new object using + * Jim_New...Obj(), but for some error we need to destroy it. + * Instead to use Jim_IncrRefCount() + Jim_DecrRefCount() we + * can just call Jim_FreeNewObj. To call Jim_Free directly + * seems too raw, the object handling may change and we want + * that Jim_FreeNewObj() can be called only against objects + * that are belived to have refcount == 0. */ +#define Jim_FreeNewObj Jim_FreeObj + +/* Free the internal representation of the object. */ +#define Jim_FreeIntRep(i,o) \ + if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \ + (o)->typePtr->freeIntRepProc(i, o) + +/* Get the internal representation pointer */ +#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr + +/* Set the internal representation pointer */ +#define Jim_SetIntRepPtr(o, p) \ + (o)->internalRep.ptr = (p) + +/* The object type structure. + * There are four methods. + * + * - FreeIntRep is used to free the internal representation of the object. + * Can be NULL if there is nothing to free. + * - DupIntRep is used to duplicate the internal representation of the object. + * If NULL, when an object is duplicated, the internalRep union is + * directly copied from an object to another. + * Note that it's up to the caller to free the old internal repr of the + * object before to call the Dup method. + * - UpdateString is used to create the string from the internal repr. + * - setFromAny is used to convert the current object into one of this type. + */ + +struct Jim_Interp; + +typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *objPtr); +typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); +typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); + +typedef struct Jim_ObjType { + const char *name; /* The name of the type. */ + Jim_FreeInternalRepProc *freeIntRepProc; + Jim_DupInternalRepProc *dupIntRepProc; + Jim_UpdateStringProc *updateStringProc; + int flags; +} Jim_ObjType; + +/* Jim_ObjType flags */ +#define JIM_TYPE_NONE 0 /* No flags */ +#define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */ + +/* Starting from 1 << 20 flags are reserved for private uses of + * different calls. This way the same 'flags' argument may be used + * to pass both global flags and private flags. */ +#define JIM_PRIV_FLAG_SHIFT 20 + +/* ----------------------------------------------------------------------------- + * Call frame, vars, commands structures + * ---------------------------------------------------------------------------*/ + +/* Call frame */ +typedef struct Jim_CallFrame { + unsigned jim_wide id; /* Call Frame ID. Used for caching. */ + int level; /* Level of this call frame. 0 = global */ + struct Jim_HashTable vars; /* Where local vars are stored */ + struct Jim_HashTable *staticVars; /* pointer to procedure static vars */ + struct Jim_CallFrame *parentCallFrame; + Jim_Obj *const *argv; /* object vector of the current procedure call. */ + int argc; /* number of args of the current procedure call. */ + Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */ + Jim_Obj *procBodyObjPtr; /* body object of the running procedure */ + struct Jim_CallFrame *nextFramePtr; + Jim_Obj *fileNameObj; /* file and line of caller of this proc (if available) */ + int line; +} Jim_CallFrame; + +/* The var structure. It just holds the pointer of the referenced + * object. If linkFramePtr is not NULL the variable is a link + * to a variable of name store on objPtr living on the given callframe + * (this happens when the [global] or [upvar] command is used). + * The interp in order to always know how to free the Jim_Obj associated + * with a given variable because In Jim objects memory managment is + * bound to interpreters. */ +typedef struct Jim_Var { + Jim_Obj *objPtr; + struct Jim_CallFrame *linkFramePtr; +} Jim_Var; + +/* The cmd structure. */ +typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, + Jim_Obj *const *argv); +typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); + + + +/* A command is implemented in C if funcPtr is != NULL, otherwise + * it's a Tcl procedure with the arglist and body represented by the + * two objects referenced by arglistObjPtr and bodyoObjPtr. */ +typedef struct Jim_Cmd { + int inUse; /* Reference count */ + int isproc; /* Is this a procedure? */ + union { + struct { + /* native (C) command */ + Jim_CmdProc cmdProc; /* The command implementation */ + Jim_DelCmdProc delProc; /* Called when the command is deleted if != NULL */ + void *privData; /* command-private data available via Jim_CmdPrivData() */ + } native; + struct { + /* Tcl procedure */ + Jim_Obj *argListObjPtr; + Jim_Obj *bodyObjPtr; + Jim_HashTable *staticVars; /* Static vars hash table. NULL if no statics. */ + struct Jim_Cmd *prevCmd; /* Previous command defn if proc created 'local' */ + int argListLen; /* Length of argListObjPtr */ + int reqArity; /* Number of required parameters */ + int optArity; /* Number of optional parameters */ + int argsPos; /* Position of 'args', if specified, or -1 */ + int upcall; /* True if proc is currently in upcall */ + struct Jim_ProcArg { + Jim_Obj *nameObjPtr; /* Name of this arg */ + Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */ + } *arglist; + } proc; + } u; +} Jim_Cmd; + +/* Pseudo Random Number Generator State structure */ +typedef struct Jim_PrngState { + unsigned char sbox[256]; + unsigned int i, j; +} Jim_PrngState; + +/* ----------------------------------------------------------------------------- + * Jim interpreter structure. + * Fields similar to the real Tcl interpreter structure have the same names. + * ---------------------------------------------------------------------------*/ +typedef struct Jim_Interp { + Jim_Obj *result; /* object returned by the last command called. */ + int errorLine; /* Error line where an error occurred. */ + Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */ + int addStackTrace; /* > 0 If a level should be added to the stack trace */ + int maxNestingDepth; /* Used for infinite loop detection. */ + int returnCode; /* Completion code to return on JIM_RETURN. */ + int returnLevel; /* Current level of 'return -level' */ + int exitCode; /* Code to return to the OS on JIM_EXIT. */ + long id; /* Hold unique id for various purposes */ + int signal_level; /* A nesting level of catch -signal */ + jim_wide sigmask; /* Bit mask of caught signals, or 0 if none */ + int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); /* Set a result for the sigmask */ + Jim_CallFrame *framePtr; /* Pointer to the current call frame */ + Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */ + struct Jim_HashTable commands; /* Commands hash table */ + unsigned jim_wide procEpoch; /* Incremented every time the result + of procedures names lookup caching + may no longer be valid. */ + unsigned jim_wide callFrameEpoch; /* Incremented every time a new + callframe is created. This id is used for the + 'ID' field contained in the Jim_CallFrame + structure. */ + int local; /* If 'local' is in effect, newly defined procs keep a reference to the old defn */ + Jim_Obj *liveList; /* Linked list of all the live objects. */ + Jim_Obj *freeList; /* Linked list of all the unused objects. */ + Jim_Obj *currentScriptObj; /* Script currently in execution. */ + Jim_Obj *emptyObj; /* Shared empty string object. */ + Jim_Obj *trueObj; /* Shared true int object. */ + Jim_Obj *falseObj; /* Shared false int object. */ + unsigned jim_wide referenceNextId; /* Next id for reference. */ + struct Jim_HashTable references; /* References hash table. */ + jim_wide lastCollectId; /* reference max Id of the last GC + execution. It's set to -1 while the collection + is running as sentinel to avoid to recursive + calls via the [collect] command inside + finalizers. */ + time_t lastCollectTime; /* unix time of the last GC execution */ + Jim_Obj *stackTrace; /* Stack trace object. */ + Jim_Obj *errorProc; /* Name of last procedure which returned an error */ + Jim_Obj *unknown; /* Unknown command cache */ + int unknown_called; /* The unknown command has been invoked */ + int errorFlag; /* Set if an error occurred during execution. */ + void *cmdPrivData; /* Used to pass the private data pointer to + a command. It is set to what the user specified + via Jim_CreateCommand(). */ + + struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ + struct Jim_HashTable assocData; /* per-interp storage for use by packages */ + Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ + struct Jim_HashTable packages; /* Provided packages hash table */ + Jim_Stack *localProcs; /* procs to be destroyed on end of evaluation */ + Jim_Stack *loadHandles; /* handles of loaded modules [load] */ +} Jim_Interp; + +/* Currently provided as macro that performs the increment. + * At some point may be a real function doing more work. + * The proc epoch is used in order to know when a command lookup + * cached can no longer considered valid. */ +#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ +#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) +#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) +/* Note: Using trueObj and falseObj here makes some things slower...*/ +#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) +#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) +#define Jim_GetResult(i) ((i)->result) +#define Jim_CmdPrivData(i) ((i)->cmdPrivData) +#define Jim_String(o) Jim_GetString((o), NULL) + +/* Note that 'o' is expanded only one time inside this macro, + * so it's safe to use side effects. */ +#define Jim_SetResult(i,o) do { \ + Jim_Obj *_resultObjPtr_ = (o); \ + Jim_IncrRefCount(_resultObjPtr_); \ + Jim_DecrRefCount(i,(i)->result); \ + (i)->result = _resultObjPtr_; \ +} while(0) + +/* Use this for filehandles, etc. which need a unique id */ +#define Jim_GetId(i) (++(i)->id) + +/* Reference structure. The interpreter pointer is held within privdata member in HashTable */ +#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference + string representation must be fixed length. */ +typedef struct Jim_Reference { + Jim_Obj *objPtr; + Jim_Obj *finalizerCmdNamePtr; + char tag[JIM_REFERENCE_TAGLEN+1]; +} Jim_Reference; + +/* ----------------------------------------------------------------------------- + * Exported API prototypes. + * ---------------------------------------------------------------------------*/ + +/* Macros that are common for extensions and core. */ +#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) + +/* The core includes real prototypes, extensions instead + * include a global function pointer for every function exported. + * Once the extension calls Jim_InitExtension(), the global + * functon pointers are set to the value of the STUB table + * contained in the Jim_Interp structure. + * + * This makes Jim able to load extensions even if it is statically + * linked itself, and to load extensions compiled with different + * versions of Jim (as long as the API is still compatible.) */ + +/* Macros are common for core and extensions */ +#define Jim_FreeHashTableIterator(iter) Jim_Free(iter) + +#define JIM_EXPORT + +/* Memory allocation */ +JIM_EXPORT void *Jim_Alloc (int size); +JIM_EXPORT void *Jim_Realloc(void *ptr, int size); +JIM_EXPORT void Jim_Free (void *ptr); +JIM_EXPORT char * Jim_StrDup (const char *s); +JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); + +/* environment */ +JIM_EXPORT char **Jim_GetEnviron(void); +JIM_EXPORT void Jim_SetEnviron(char **env); + +/* evaluation */ +JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); +/* in C code, you can do this and get better error messages */ +/* Jim_EvalSource( interp, __FILE__, __LINE__ , "some tcl commands"); */ +JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); +/* Backwards compatibility */ +#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S)) + +JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script); +JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr); +JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); +JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, + int objc, Jim_Obj *const *objv); +#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov)) +JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr, + Jim_Obj **resObjPtrPtr, int flags); + +/* stack */ +JIM_EXPORT void Jim_InitStack(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack); +JIM_EXPORT int Jim_StackLen(Jim_Stack *stack); +JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element); +JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack); +JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr)); + +/* hash table */ +JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht, + const Jim_HashTableType *type, void *privdata); +JIM_EXPORT int Jim_ExpandHashTable (Jim_HashTable *ht, + unsigned int size); +JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key, + void *val); +JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht, + const void *key, void *val); +JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT int Jim_ResizeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator + (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry + (Jim_HashTableIterator *iter); + +/* objects */ +JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); +JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); +JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes, + int length); +JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, + int *lenPtr); +JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); + +/* string object */ +JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp, + const char *s, int len); +JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, + const char *s, int charlen); +JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp, + char *s, int len); +JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr, + const char *str, int len); +JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *appendObjPtr); +JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp, + Jim_Obj *objPtr, ...); +JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr); +JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr, + Jim_Obj *objPtr, int nocase); +JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr); +JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp, + Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv); +JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr, + Jim_Obj *fmtObjPtr, int flags); +JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, + Jim_Obj *objPtr, const char *str); +JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, + Jim_Obj *secondObjPtr, int nocase); +JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); + +/* reference object */ +JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, + Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr); + +/* interpreter */ +JIM_EXPORT Jim_Interp * Jim_CreateInterp (void); +JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i); +JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp); +JIM_EXPORT const char *Jim_ReturnCode(int code); +JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...); + +/* commands */ +JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); +JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, + const char *cmdName, Jim_CmdProc cmdProc, void *privData, + Jim_DelCmdProc delProc); +JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, + const char *cmdName); +JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, + const char *oldName, const char *newName); +JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, + Jim_Obj *objPtr, int flags); +JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); +JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, + const char *name, const char *val); +JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, + Jim_CallFrame *targetCallFrame); +JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); + +/* call frame */ +JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, + Jim_Obj *levelObjPtr); + +/* garbage collection */ +JIM_EXPORT int Jim_Collect (Jim_Interp *interp); +JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp); + +/* index object */ +JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr, + int *indexPtr); + +/* list object */ +JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp, + Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec); +JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *objPtr); +JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *appendListPtr); +JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt, + int listindex, Jim_Obj **objPtrPtr, int seterr); +JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, + Jim_Obj *newObjPtr); +JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); + +/* dict object */ +JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj *newObjPtr, int flags); +JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); +JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); +JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); +JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); + +/* return code object */ +JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, + int *intPtr); + +/* expression object */ +JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, + Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); +JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, + Jim_Obj *exprObjPtr, int *boolPtr); + +/* integer object */ +JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, + jim_wide *widePtr); +JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, + long *longPtr); +#define Jim_NewWideObj Jim_NewIntObj +JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, + jim_wide wideValue); + +/* double object */ +JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double *doublePtr); +JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double doubleValue); +JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); + +/* shared strings */ +JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp, + const char *str); +JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp, + const char *str); + +/* commands utilities */ +JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, + Jim_Obj *const *argv, const char *msg); +JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, + const char * const *tablePtr, int *indexPtr, const char *name, int flags); +JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len, + char *stateCharPtr); +/** + * Find a matching name in the array of the given length. + * + * NULL entries are ignored. + * + * Returns the matching index if found, or -1 if not. + */ +JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); + +/* package utilities */ +typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); +JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); +JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, + Jim_InterpDeleteProc *delProc, void *data); +JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); + +/* Packages C API */ +/* jim-package.c */ +JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, + const char *name, const char *ver, int flags); +JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, + const char *name, int flags); + +/* error messages */ +JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); + +/* interactive mode */ +JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); + +/* Misc */ +JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); +JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); + +/* jim-load.c */ +JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); +JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); + +/* jim-aio.c */ +JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); + + +/* type inspection - avoid where possible */ +JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); +JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); + +#ifdef __cplusplus +} +#endif + +#endif /* __JIM__H */ + +/* + * Local Variables: *** + * c-basic-offset: 4 *** + * tab-width: 4 *** + * End: *** + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in b/android/external/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in new file mode 100755 index 0000000..f4eb0e5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in @@ -0,0 +1,145 @@ +/* jimautoconf.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Have the dlopen function */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if the system has the type `long long'. */ +#undef HAVE_LONG_LONG + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Have libreadline */ +#undef HAVE_READLINE + +/* Define to 1 if you have the `readlink' function. */ +#undef HAVE_READLINK + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `regcomp' function. */ +#undef HAVE_REGCOMP + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Have libsqlite */ +#undef HAVE_SQLITE + +/* Have libsqlite3 */ +#undef HAVE_SQLITE3 + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strptime' function. */ +#undef HAVE_STRPTIME + +/* Define to 1 if you have the `sysinfo' function. */ +#undef HAVE_SYSINFO + +/* Define to 1 if you have the `syslog' function. */ +#undef HAVE_SYSLOG + +/* Define to 1 if you have the `sys_siglist' function. */ +#undef HAVE_SYS_SIGLIST + +/* Define to 1 if you have the `sys_signame' function. */ +#undef HAVE_SYS_SIGNAME + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <sys/un.h> header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if you have the <termios.h> header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the `ualarm' function. */ +#undef HAVE_UALARM + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + +/* No need to declare extern 'environ'. */ +#undef NO_ENVIRON_EXTERN + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.c new file mode 100755 index 0000000..c652ad4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.c @@ -0,0 +1,1756 @@ +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to | + *** to assist in implementing egrep. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching + *** as in BSD grep and ex. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \. + *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods, + *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy. + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@vix.com, on 28 August 1993, for use in jam. Regmagic.h + *** was moved into regexp.h, and the include of regexp.h now uses "'s + *** to avoid conflicting with the system regexp.h. Const, bless its + *** soul, was removed so it can compile everywhere. The declaration + *** of strchr() was in conflict on AIX, so it was removed (as it is + *** happily defined in string.h). + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@perforce.com, on 20 January 2000, to use function prototypes. + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@perforce.com, on 05 November 2002, to const string literals. + * + * THIS IS AN ALTERED VERSION. It was altered by Steve Bennett <steveb@workware.net.au> + * on 16 October 2010, to remove static state and add better Tcl ARE compatibility. + * This includes counted repetitions, UTF-8 support, character classes, + * shorthand character classes, increased number of parentheses to 100, + * backslash escape sequences. It also removes \n as an alternative to |. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jimregexp.h" +#include "utf8.h" + +#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP) + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* This *MUST* be less than (255-20)/2=117 */ +#define REG_MAX_PAREN 100 + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define REP 10 /* max,min Match this (simple) thing [min,max] times. */ +#define REPMIN 11 /* max,min Match this (simple) thing [min,max] times, mininal match. */ +#define REPX 12 /* max,min Match this (complex) thing [min,max] times. */ +#define REPXMIN 13 /* max,min Match this (complex) thing [min,max] times, minimal match. */ + +#define WORDA 15 /* no Match "" at wordchar, where prev is nonword */ +#define WORDZ 16 /* no Match "" at nonwordchar, where prev is word */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE (OPEN+REG_MAX_PAREN) /* no Analogous to OPEN. */ +#define CLOSE_END (CLOSE+REG_MAX_PAREN) + +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define REG_MAGIC 0xFADED00D + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(preg, p) (preg->program[p]) +#define NEXT(preg, p) (preg->program[p + 1]) +#define OPERAND(p) ((p) + 2) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ + +#define FAIL(R,M) { (R)->err = (M); return (M); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') +#define META "^$.[()|?{+*" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +#define MAX_REP_COUNT 1000000 + +/* + * Forward declarations for regcomp()'s friends. + */ +static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp ); +static int regpiece(regex_t *preg, int *flagp ); +static int regbranch(regex_t *preg, int *flagp ); +static int regatom(regex_t *preg, int *flagp ); +static int regnode(regex_t *preg, int op ); +static int regnext(regex_t *preg, int p ); +static void regc(regex_t *preg, int b ); +static int reginsert(regex_t *preg, int op, int size, int opnd ); +static void regtail_(regex_t *preg, int p, int val, int line ); +static void regoptail(regex_t *preg, int p, int val ); +#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__) + +static int reg_range_find(const int *string, int c); +static const char *str_find(const char *string, int c, int nocase); +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); + +/*#define DEBUG*/ +#ifdef DEBUG +int regnarrate = 0; +static void regdump(regex_t *preg); +static const char *regprop( int op ); +#endif + + +/** + * Returns the length of the null-terminated integer sequence. + */ +static int str_int_len(const int *seq) +{ + int n = 0; + while (*seq++) { + n++; + } + return n; +} + +/* + - regcomp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ +int regcomp(regex_t *preg, const char *exp, int cflags) +{ + int scan; + int longest; + unsigned len; + int flags; + +#ifdef DEBUG + fprintf(stderr, "Compiling: '%s'\n", exp); +#endif + memset(preg, 0, sizeof(*preg)); + + if (exp == NULL) + FAIL(preg, REG_ERR_NULL_ARGUMENT); + + /* First pass: determine size, legality. */ + preg->cflags = cflags; + preg->regparse = exp; + /* XXX: For now, start unallocated */ + preg->program = NULL; + preg->proglen = 0; + +#if 1 + /* Allocate space. */ + preg->proglen = (strlen(exp) + 1) * 5; + preg->program = malloc(preg->proglen * sizeof(int)); + if (preg->program == NULL) + FAIL(preg, REG_ERR_NOMEM); +#endif + + /* Note that since we store a magic value as the first item in the program, + * program offsets will never be 0 + */ + regc(preg, REG_MAGIC); + if (reg(preg, 0, &flags) == 0) { + return preg->err; + } + + /* Small enough for pointer-storage convention? */ + if (preg->re_nsub >= REG_MAX_PAREN) /* Probably could be 65535L. */ + FAIL(preg,REG_ERR_TOO_BIG); + + /* Dig out information for optimizations. */ + preg->regstart = 0; /* Worst-case defaults. */ + preg->reganch = 0; + preg->regmust = 0; + preg->regmlen = 0; + scan = 1; /* First BRANCH. */ + if (OP(preg, regnext(preg, scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(preg, scan) == EXACTLY) { + preg->regstart = preg->program[OPERAND(scan)]; + } + else if (OP(preg, scan) == BOL) + preg->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = 0; + len = 0; + for (; scan != 0; scan = regnext(preg, scan)) { + if (OP(preg, scan) == EXACTLY) { + int plen = str_int_len(preg->program + OPERAND(scan)); + if (plen >= len) { + longest = OPERAND(scan); + len = plen; + } + } + } + preg->regmust = longest; + preg->regmlen = len; + } + } + +#ifdef DEBUG + regdump(preg); +#endif + + return 0; +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp ) +{ + int ret; + int br; + int ender; + int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + parno = ++preg->re_nsub; + ret = regnode(preg, OPEN+parno); + } else + ret = 0; + + /* Pick up the branches, linking them together. */ + br = regbranch(preg, &flags); + if (br == 0) + return 0; + if (ret != 0) + regtail(preg, ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*preg->regparse == '|') { + preg->regparse++; + br = regbranch(preg, &flags); + if (br == 0) + return 0; + regtail(preg, ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode(preg, (paren) ? CLOSE+parno : END); + regtail(preg, ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != 0; br = regnext(preg, br)) + regoptail(preg, br, ender); + + /* Check for proper termination. */ + if (paren && *preg->regparse++ != ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else if (!paren && *preg->regparse != '\0') { + if (*preg->regparse == ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else { + preg->err = REG_ERR_JUNK_ON_END; + return 0; + } + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static int regbranch(regex_t *preg, int *flagp ) +{ + int ret; + int chain; + int latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(preg, BRANCH); + chain = 0; + while (*preg->regparse != '\0' && *preg->regparse != ')' && + *preg->regparse != '|') { + latest = regpiece(preg, &flags); + if (latest == 0) + return 0; + *flagp |= flags&HASWIDTH; + if (chain == 0) {/* First piece. */ + *flagp |= flags&SPSTART; + } + else { + regtail(preg, chain, latest); + } + chain = latest; + } + if (chain == 0) /* Loop ran zero times. */ + (void) regnode(preg, NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static int regpiece(regex_t *preg, int *flagp) +{ + int ret; + char op; + int next; + int flags; + int chain = 0; + int min; + int max; + + ret = regatom(preg, &flags); + if (ret == 0) + return 0; + + op = *preg->regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') { + preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; + return 0; + } + + /* Handle braces (counted repetition) by expansion */ + if (op == '{') { + char *end; + + min = strtoul(preg->regparse + 1, &end, 10); + if (end == preg->regparse + 1) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (*end == '}') { + max = min; + } + else { + preg->regparse = end; + max = strtoul(preg->regparse + 1, &end, 10); + if (*end != '}') { + preg->err = REG_ERR_UNMATCHED_BRACES; + return 0; + } + } + if (end == preg->regparse + 1) { + max = MAX_REP_COUNT; + } + else if (max < min || max >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (min >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + + preg->regparse = strchr(preg->regparse, '}'); + } + else { + min = (op == '+'); + max = (op == '?' ? 1 : MAX_REP_COUNT); + } + + if (preg->regparse[1] == '?') { + preg->regparse++; + next = reginsert(preg, flags & SIMPLE ? REPMIN : REPXMIN, 5, ret); + } + else { + next = reginsert(preg, flags & SIMPLE ? REP: REPX, 5, ret); + } + preg->program[ret + 2] = max; + preg->program[ret + 3] = min; + preg->program[ret + 4] = 0; + + *flagp = (min) ? (WORST|HASWIDTH) : (WORST|SPSTART); + + if (!(flags & SIMPLE)) { + int back = regnode(preg, BACK); + regtail(preg, back, ret); + regtail(preg, next, back); + } + + preg->regparse++; + if (ISMULT(*preg->regparse)) { + preg->err = REG_ERR_NESTED_COUNT; + return 0; + } + + return chain ? chain : ret; +} + +/** + * Add all characters in the inclusive range between lower and upper. + * + * Handles a swapped range (upper < lower). + */ +static void reg_addrange(regex_t *preg, int lower, int upper) +{ + if (lower > upper) { + reg_addrange(preg, upper, lower); + } + /* Add a range as length, start */ + regc(preg, upper - lower + 1); + regc(preg, lower); +} + +/** + * Add a null-terminated literal string as a set of ranges. + */ +static void reg_addrange_str(regex_t *preg, const char *str) +{ + while (*str) { + reg_addrange(preg, *str, *str); + str++; + } +} + +/** + * Extracts the next unicode char from utf8. + * + * If 'upper' is set, converts the char to uppercase. + */ +static int reg_utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + +/** + * Converts a hex digit to decimal. + * + * Returns -1 for an invalid hex digit. + */ +static int hexdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +/** + * Parses up to 'n' hex digits at 's' and stores the result in *uc. + * + * Returns the number of hex digits parsed. + * If there are no hex digits, returns 0 and stores nothing. + */ +static int parse_hex(const char *s, int n, int *uc) +{ + int val = 0; + int k; + + for (k = 0; k < n; k++) { + int c = hexdigitval(*s++); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + if (k) { + *uc = val; + } + return k; +} + +/** + * Call for chars after a backlash to decode the escape sequence. + * + * Stores the result in *ch. + * + * Returns the number of bytes consumed. + */ +static int reg_decode_escape(const char *s, int *ch) +{ + int n; + const char *s0 = s; + + *ch = *s++; + + switch (*ch) { + case 'b': *ch = '\b'; break; + case 'e': *ch = 27; break; + case 'f': *ch = '\f'; break; + case 'n': *ch = '\n'; break; + case 'r': *ch = '\r'; break; + case 't': *ch = '\t'; break; + case 'v': *ch = '\v'; break; + case 'u': + if ((n = parse_hex(s, 4, ch)) > 0) { + s += n; + } + break; + case 'x': + if ((n = parse_hex(s, 2, ch)) > 0) { + s += n; + } + break; + case '\0': + s--; + *ch = '\\'; + break; + } + return s - s0; +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static int regatom(regex_t *preg, int *flagp) +{ + int ret; + int flags; + int nocase = (preg->cflags & REG_ICASE); + + int ch; + int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); + + *flagp = WORST; /* Tentatively. */ + + preg->regparse += n; + switch (ch) { + /* FIXME: these chars only have meaning at beg/end of pat? */ + case '^': + ret = regnode(preg, BOL); + break; + case '$': + ret = regnode(preg, EOL); + break; + case '.': + ret = regnode(preg, ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + const char *pattern = preg->regparse; + + if (*pattern == '^') { /* Complement of range. */ + ret = regnode(preg, ANYBUT); + pattern++; + } else + ret = regnode(preg, ANYOF); + + /* Special case. If the first char is ']' or '-', it is part of the set */ + if (*pattern == ']' || *pattern == '-') { + reg_addrange(preg, *pattern, *pattern); + pattern++; + } + + while (*pattern && *pattern != ']') { + /* Is this a range? a-z */ + int start; + int end; + + pattern += reg_utf8_tounicode_case(pattern, &start, nocase); + if (start == '\\') { + pattern += reg_decode_escape(pattern, &start); + if (start == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + if (pattern[0] == '-' && pattern[1]) { + /* skip '-' */ + pattern += utf8_tounicode(pattern, &end); + pattern += reg_utf8_tounicode_case(pattern, &end, nocase); + if (end == '\\') { + pattern += reg_decode_escape(pattern, &end); + if (end == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + reg_addrange(preg, start, end); + continue; + } + if (start == '[') { + if (strncmp(pattern, ":alpha:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":alnum:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":space:]", 8) == 0) { + reg_addrange_str(preg, " \t\r\n\f\v"); + pattern += 8; + continue; + } + } + /* Not a range, so just add the char */ + reg_addrange(preg, start, start); + } + regc(preg, '\0'); + + if (*pattern) { + pattern++; + } + preg->regparse = pattern; + + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(preg, 1, &flags); + if (ret == 0) + return 0; + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + preg->err = REG_ERR_INTERNAL; + return 0; /* Supposed to be caught earlier. */ + case '?': + case '+': + case '*': + case '{': + preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; + return 0; + case '\\': + switch (*preg->regparse++) { + case '\0': + preg->err = REG_ERR_TRAILING_BACKSLASH; + return 0; + case '<': + case 'm': + ret = regnode(preg, WORDA); + break; + case '>': + case 'M': + ret = regnode(preg, WORDZ); + break; + case 'd': + ret = regnode(preg, ANYOF); + reg_addrange(preg, '0', '9'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 'w': + ret = regnode(preg, ANYOF); + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + reg_addrange(preg, '_', '_'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 's': + ret = regnode(preg, ANYOF); + reg_addrange_str(preg," \t\r\n\f\v"); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + /* FIXME: Someday handle \1, \2, ... */ + default: + /* Handle general quoted chars in exact-match routine */ + /* Back up to include the backslash */ + preg->regparse--; + goto de_fault; + } + break; + de_fault: + default: { + /* + * Encode a string of characters to be matched exactly. + */ + int added = 0; + + /* Back up to pick up the first char of interest */ + preg->regparse -= n; + + ret = regnode(preg, EXACTLY); + + /* Note that a META operator such as ? or * consumes the + * preceding char. + * Thus we must be careful to look ahead by 2 and add the + * last char as it's own EXACTLY if necessary + */ + + /* Until end of string or a META char is reached */ + while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { + n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); + if (ch == '\\' && preg->regparse[n]) { + /* Non-trailing backslash. + * Is this a special escape, or a regular escape? + */ + if (strchr("<>mMwds", preg->regparse[n])) { + /* A special escape. All done with EXACTLY */ + break; + } + /* Decode it. Note that we add the length for the escape + * sequence to the length for the backlash so we can skip + * the entire sequence, or not as required. + */ + n += reg_decode_escape(preg->regparse + n, &ch); + if (ch == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + /* Now we have one char 'ch' of length 'n'. + * Check to see if the following char is a MULT + */ + + if (ISMULT(preg->regparse[n])) { + /* Yes. But do we already have some EXACTLY chars? */ + if (added) { + /* Yes, so return what we have and pick up the current char next time around */ + break; + } + /* No, so add this single char and finish */ + regc(preg, ch); + added++; + preg->regparse += n; + break; + } + + /* No, so just add this char normally */ + regc(preg, ch); + added++; + preg->regparse += n; + } + regc(preg, '\0'); + + *flagp |= HASWIDTH; + if (added == 1) + *flagp |= SIMPLE; + break; + } + break; + } + + return(ret); +} + +static void reg_grow(regex_t *preg, int n) +{ + if (preg->p + n >= preg->proglen) { + preg->proglen = (preg->p + n) * 2; + preg->program = realloc(preg->program, preg->proglen * sizeof(int)); + } +} + +/* + - regnode - emit a node + */ +/* Location. */ +static int regnode(regex_t *preg, int op) +{ + reg_grow(preg, 2); + + preg->program[preg->p++] = op; + preg->program[preg->p++] = 0; + + /* Return the start of the node */ + return preg->p - 2; +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void regc(regex_t *preg, int b ) +{ + reg_grow(preg, 1); + preg->program[preg->p++] = b; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + * Returns the new location of the original operand. + */ +static int reginsert(regex_t *preg, int op, int size, int opnd ) +{ + reg_grow(preg, size); + + /* Move everything from opnd up */ + memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); + /* Zero out the new space */ + memset(preg->program + opnd, 0, sizeof(int) * size); + + preg->program[opnd] = op; + + preg->p += size; + + return opnd + size; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void regtail_(regex_t *preg, int p, int val, int line ) +{ + int scan; + int temp; + int offset; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(preg, scan); + if (temp == 0) + break; + scan = temp; + } + + if (OP(preg, scan) == BACK) + offset = scan - val; + else + offset = val - scan; + + preg->program[scan + 1] = offset; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ + +static void regoptail(regex_t *preg, int p, int val ) +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p != 0 && OP(preg, p) == BRANCH) { + regtail(preg, OPERAND(p), val); + } +} + +/* + * regexec and friends + */ + +/* + * Forwards. + */ +static int regtry(regex_t *preg, const char *string ); +static int regmatch(regex_t *preg, int prog); +static int regrepeat(regex_t *preg, int p, int max); + +/* + - regexec - match a regexp against a string + */ +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) +{ + const char *s; + int scan; + + /* Be paranoid... */ + if (preg == NULL || preg->program == NULL || string == NULL) { + return REG_ERR_NULL_ARGUMENT; + } + + /* Check validity of program. */ + if (*preg->program != REG_MAGIC) { + return REG_ERR_CORRUPTED; + } + +#ifdef DEBUG + fprintf(stderr, "regexec: %s\n", string); + regdump(preg); +#endif + + preg->eflags = eflags; + preg->pmatch = pmatch; + preg->nmatch = nmatch; + preg->start = string; /* All offsets are computed from here */ + + /* Must clear out the embedded repeat counts */ + for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) { + switch (OP(preg, scan)) { + case REP: + case REPMIN: + case REPX: + case REPXMIN: + preg->program[scan + 4] = 0; + break; + } + } + + /* If there is a "must appear" string, look for it. */ + if (preg->regmust != 0) { + s = string; + while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { + if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { + break; + } + s++; + } + if (s == NULL) /* Not present. */ + return REG_NOMATCH; + } + + /* Mark beginning of line for ^ . */ + preg->regbol = string; + + /* Simplest case: anchored match need be tried only once (maybe per line). */ + if (preg->reganch) { + if (eflags & REG_NOTBOL) { + /* This is an anchored search, but not an BOL, so possibly skip to the next line */ + goto nextline; + } + while (1) { + int ret = regtry(preg, string); + if (ret) { + return REG_NOERROR; + } + if (*string) { +nextline: + if (preg->cflags & REG_NEWLINE) { + /* Try the next anchor? */ + string = strchr(string, '\n'); + if (string) { + preg->regbol = ++string; + continue; + } + } + } + return REG_NOMATCH; + } + } + + /* Messy cases: unanchored match. */ + s = string; + if (preg->regstart != '\0') { + /* We know what char it must start with. */ + while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { + if (regtry(preg, s)) + return REG_NOERROR; + s++; + } + } + else + /* We don't -- general case. */ + while (1) { + if (regtry(preg, s)) + return REG_NOERROR; + if (*s == '\0') { + break; + } + s += utf8_charlen(*s); + } + + /* Failure. */ + return REG_NOMATCH; +} + +/* + - regtry - try match at specific point + */ + /* 0 failure, 1 success */ +static int regtry( regex_t *preg, const char *string ) +{ + int i; + + preg->reginput = string; + + for (i = 0; i < preg->nmatch; i++) { + preg->pmatch[i].rm_so = -1; + preg->pmatch[i].rm_eo = -1; + } + if (regmatch(preg, 1)) { + preg->pmatch[0].rm_so = string - preg->start; + preg->pmatch[0].rm_eo = preg->reginput - preg->start; + return(1); + } else + return(0); +} + +/** + * Returns bytes matched if 'pattern' is a prefix of 'string'. + * + * If 'nocase' is non-zero, does a case-insensitive match. + * + * Returns -1 on not found. + */ +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase) +{ + const char *s = string; + while (proglen && *s) { + int ch; + int n = reg_utf8_tounicode_case(s, &ch, nocase); + if (ch != *prog) { + return -1; + } + prog++; + s += n; + proglen--; + } + if (proglen == 0) { + return s - string; + } + return -1; +} + +/** + * Searchs for 'c' in the range 'range'. + * + * Returns 1 if found, or 0 if not. + */ +static int reg_range_find(const int *range, int c) +{ + while (*range) { + /*printf("Checking %d in range [%d,%d]\n", c, range[1], (range[0] + range[1] - 1));*/ + if (c >= range[1] && c <= (range[0] + range[1] - 1)) { + return 1; + } + range += 2; + } + return 0; +} + +/** + * Search for the character 'c' in the utf-8 string 'string'. + * + * If 'nocase' is set, the 'string' is assumed to be uppercase + * and 'c' is converted to uppercase before matching. + * + * Returns the byte position in the string where the 'c' was found, or + * NULL if not found. + */ +static const char *str_find(const char *string, int c, int nocase) +{ + if (nocase) { + /* The "string" should already be converted to uppercase */ + c = utf8_upper(c); + } + while (*string) { + int ch; + int n = reg_utf8_tounicode_case(string, &ch, nocase); + if (c == ch) { + return string; + } + string += n; + } + return NULL; +} + +/** + * Returns true if 'ch' is an end-of-line char. + * + * In REG_NEWLINE mode, \n is considered EOL in + * addition to \0 + */ +static int reg_iseol(regex_t *preg, int ch) +{ + if (preg->cflags & REG_NEWLINE) { + return ch == '\0' || ch == '\n'; + } + else { + return ch == '\0'; + } +} + +static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin) +{ + int nextch = '\0'; + const char *save; + int no; + int c; + + int max = preg->program[scan + 2]; + int min = preg->program[scan + 3]; + int next = regnext(preg, scan); + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + if (OP(preg, next) == EXACTLY) { + nextch = preg->program[OPERAND(next)]; + } + save = preg->reginput; + no = regrepeat(preg, scan + 5, max); + if (no < min) { + return 0; + } + if (matchmin) { + /* from min up to no */ + max = no; + no = min; + } + /* else from no down to min */ + while (1) { + if (matchmin) { + if (no > max) { + break; + } + } + else { + if (no < min) { + break; + } + } + preg->reginput = save + utf8_index(save, no); + reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + /* If it could work, try it. */ + if (reg_iseol(preg, nextch) || c == nextch) { + if (regmatch(preg, next)) { + return(1); + } + } + if (matchmin) { + /* Couldn't or didn't, add one more */ + no++; + } + else { + /* Couldn't or didn't -- back up. */ + no--; + } + } + return(0); +} + +static int regmatchrepeat(regex_t *preg, int scan, int matchmin) +{ + int *scanpt = preg->program + scan; + + int max = scanpt[2]; + int min = scanpt[3]; + + /* Have we reached min? */ + if (scanpt[4] < min) { + /* No, so get another one */ + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + if (scanpt[4] > max) { + return 0; + } + + if (matchmin) { + /* minimal, so try other branch first */ + if (regmatch(preg, regnext(preg, scan))) { + return 1; + } + /* No, so try one more */ + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + /* maximal, so try this branch again */ + if (scanpt[4] < max) { + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + } + /* At this point we are at max with no match. Try the other branch */ + return regmatch(preg, regnext(preg, scan)); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +/* 0 failure, 1 success */ +static int regmatch(regex_t *preg, int prog) +{ + int scan; /* Current node. */ + int next; /* Next node. */ + + scan = prog; + +#ifdef DEBUG + if (scan != 0 && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != 0) { + int n; + int c; +#ifdef DEBUG + if (regnarrate) { + fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); /* Where, what. */ + } +#endif + next = regnext(preg, scan); + n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + + switch (OP(preg, scan)) { + case BOL: + if (preg->reginput != preg->regbol) + return(0); + break; + case EOL: + if (!reg_iseol(preg, c)) { + return(0); + } + break; + case WORDA: + /* Must be looking at a letter, digit, or _ */ + if ((!isalnum(UCHAR(c))) && c != '_') + return(0); + /* Prev must be BOL or nonword */ + if (preg->reginput > preg->regbol && + (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) + return(0); + break; + case WORDZ: + /* Can't match at BOL */ + if (preg->reginput > preg->regbol) { + /* Current must be EOL or nonword */ + if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { + c = preg->reginput[-1]; + /* Previous must be word */ + if (isalnum(UCHAR(c)) || c == '_') { + break; + } + } + } + /* No */ + return(0); + + case ANY: + if (reg_iseol(preg, c)) + return 0; + preg->reginput += n; + break; + case EXACTLY: { + int opnd; + int len; + int slen; + + opnd = OPERAND(scan); + len = str_int_len(preg->program + opnd); + + slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE); + if (slen < 0) { + return(0); + } + preg->reginput += slen; + } + break; + case ANYOF: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) { + return(0); + } + preg->reginput += n; + break; + case ANYBUT: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) { + return(0); + } + preg->reginput += n; + break; + case NOTHING: + break; + case BACK: + break; + case BRANCH: { + const char *save; + + if (OP(preg, next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = preg->reginput; + if (regmatch(preg, OPERAND(scan))) { + return(1); + } + preg->reginput = save; + scan = regnext(preg, scan); + } while (scan != 0 && OP(preg, scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case REP: + case REPMIN: + return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); + + case REPX: + case REPXMIN: + return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); + + case END: + return(1); /* Success! */ + break; + default: + if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { + const char *save; + + save = preg->reginput; + + if (regmatch(preg, next)) { + int no; + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (OP(preg, scan) < CLOSE) { + no = OP(preg, scan) - OPEN; + if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { + preg->pmatch[no].rm_so = save - preg->start; + } + } + else { + no = OP(preg, scan) - CLOSE; + if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { + preg->pmatch[no].rm_eo = save - preg->start; + } + } + return(1); + } else + return(0); + } + return REG_ERR_INTERNAL; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + return REG_ERR_INTERNAL; +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int regrepeat(regex_t *preg, int p, int max) +{ + int count = 0; + const char *scan; + int opnd; + int ch; + int n; + + scan = preg->reginput; + opnd = OPERAND(p); + switch (OP(preg, p)) { + case ANY: + /* No need to handle utf8 specially here */ + while (!reg_iseol(preg, *scan) && count < max) { + count++; + scan++; + } + break; + case EXACTLY: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (preg->program[opnd] != ch) { + break; + } + count++; + scan += n; + } + break; + case ANYOF: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) == 0) { + break; + } + count++; + scan += n; + } + break; + case ANYBUT: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) != 0) { + break; + } + count++; + scan += n; + } + break; + default: /* Oh dear. Called inappropriately. */ + preg->err = REG_ERR_INTERNAL; + count = 0; /* Best compromise. */ + break; + } + preg->reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static int regnext(regex_t *preg, int p ) +{ + int offset; + + offset = NEXT(preg, p); + + if (offset == 0) + return 0; + + if (OP(preg, p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#if defined(DEBUG) && !defined(JIM_BOOTSTRAP) + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +static void regdump(regex_t *preg) +{ + int s; + int op = EXACTLY; /* Arbitrary non-END op. */ + int next; + char buf[4]; + + int i; + for (i = 1; i < preg->p; i++) { + printf("%02x ", preg->program[i]); + if (i % 16 == 15) { + printf("\n"); + } + } + printf("\n"); + + s = 1; + while (op != END && s < preg->p) { /* While that wasn't END last time... */ + op = OP(preg, s); + printf("%3d: %s", s, regprop(op)); /* Where, what. */ + next = regnext(preg, s); + if (next == 0) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", next); + s += 2; + if (op == REP || op == REPMIN || op == REPX || op == REPXMIN) { + int max = preg->program[s]; + int min = preg->program[s + 1]; + if (max == 65535) { + printf("{%d,*}", min); + } + else { + printf("{%d,%d}", min, max); + } + printf(" %d", preg->program[s + 2]); + s += 3; + } + else if (op == ANYOF || op == ANYBUT) { + /* set of ranges */ + + while (preg->program[s]) { + int len = preg->program[s++]; + int first = preg->program[s++]; + buf[utf8_fromunicode(buf, first)] = 0; + printf("%s", buf); + if (len > 1) { + buf[utf8_fromunicode(buf, first + len - 1)] = 0; + printf("-%s", buf); + } + } + s++; + } + else if (op == EXACTLY) { + /* Literal string, where present. */ + + while (preg->program[s]) { + buf[utf8_fromunicode(buf, preg->program[s])] = 0; + printf("%s", buf); + s++; + } + s++; + } + putchar('\n'); + } + + if (op == END) { + /* Header fields of interest. */ + if (preg->regstart) { + buf[utf8_fromunicode(buf, preg->regstart)] = 0; + printf("start '%s' ", buf); + } + if (preg->reganch) + printf("anchored "); + if (preg->regmust != 0) { + int i; + printf("must have:"); + for (i = 0; i < preg->regmlen; i++) { + putchar(preg->program[preg->regmust + i]); + } + putchar('\n'); + } + } + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static const char *regprop( int op ) +{ + static char buf[50]; + + switch (op) { + case BOL: + return "BOL"; + case EOL: + return "EOL"; + case ANY: + return "ANY"; + case ANYOF: + return "ANYOF"; + case ANYBUT: + return "ANYBUT"; + case BRANCH: + return "BRANCH"; + case EXACTLY: + return "EXACTLY"; + case NOTHING: + return "NOTHING"; + case BACK: + return "BACK"; + case END: + return "END"; + case REP: + return "REP"; + case REPMIN: + return "REPMIN"; + case REPX: + return "REPX"; + case REPXMIN: + return "REPXMIN"; + case WORDA: + return "WORDA"; + case WORDZ: + return "WORDZ"; + default: + if (op >= OPEN && op < CLOSE) { + snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN); + } + else if (op >= CLOSE && op < CLOSE_END) { + snprintf(buf, sizeof(buf), "CLOSE%d", op-CLOSE); + } + else { + snprintf(buf, sizeof(buf), "?%d?\n", op); + } + return(buf); + } +} +#endif /* JIM_BOOTSTRAP */ + +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) +{ + static const char *error_strings[] = { + "success", + "no match", + "bad pattern", + "null argument", + "unknown error", + "too big", + "out of memory", + "too many ()", + "parentheses () not balanced", + "braces {} not balanced", + "invalid repetition count(s)", + "extra characters", + "*+ of empty atom", + "nested count", + "internal error", + "count follows nothing", + "trailing backslash", + "corrupted program", + "contains null char", + }; + const char *err; + + if (errcode < 0 || errcode >= REG_ERR_NUM) { + err = "Bad error code"; + } + else { + err = error_strings[errcode]; + } + + return snprintf(errbuf, errbuf_size, "%s", err); +} + +void regfree(regex_t *preg) +{ + free(preg->program); +} + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.h b/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.h new file mode 100755 index 0000000..79a87e5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jimregexp.h @@ -0,0 +1,117 @@ +#ifndef JIMREGEXP_H +#define JIMREGEXP_H + +#ifndef _JIMAUTOCONF_H +#error Need jimautoconf.h +#endif + +#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP) +/* Use POSIX regex */ +#include <regex.h> + +#else + +#include <stdlib.h> + +/* + * Definitions etc. for regexp(3) routines. + * + * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], + * not the System V one. + * + * 11/04/02 (seiwald) - const-ing for string literals + */ + +typedef struct { + int rm_so; + int rm_eo; +} regmatch_t; + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +typedef struct regexp { + /* -- public -- */ + int re_nsub; /* number of parenthesized subexpressions */ + + /* -- private -- */ + int cflags; /* Flags used when compiling */ + int err; /* Any error which occurred during compile */ + int regstart; /* Internal use only. */ + int reganch; /* Internal use only. */ + int regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + int *program; /* Allocated */ + + /* working state - compile */ + const char *regparse; /* Input-scan pointer. */ + int p; /* Current output pos in program */ + int proglen; /* Allocated program size */ + + /* working state - exec */ + int eflags; /* Flags used when executing */ + const char *start; /* Initial string pointer. */ + const char *reginput; /* Current input pointer. */ + const char *regbol; /* Beginning of input, for ^ check. */ + + /* Input to regexec() */ + regmatch_t *pmatch; /* submatches will be stored here */ + int nmatch; /* size of pmatch[] */ +} regexp; + +typedef regexp regex_t; + +#define REG_EXTENDED 0 +#define REG_NEWLINE 1 +#define REG_ICASE 2 + +#define REG_NOTBOL 16 + +enum { + REG_NOERROR, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + REG_BADPAT, /* >= REG_BADPAT is an error */ + REG_ERR_NULL_ARGUMENT, + REG_ERR_UNKNOWN, + REG_ERR_TOO_BIG, + REG_ERR_NOMEM, + REG_ERR_TOO_MANY_PAREN, + REG_ERR_UNMATCHED_PAREN, + REG_ERR_UNMATCHED_BRACES, + REG_ERR_BAD_COUNT, + REG_ERR_JUNK_ON_END, + REG_ERR_OPERAND_COULD_BE_EMPTY, + REG_ERR_NESTED_COUNT, + REG_ERR_INTERNAL, + REG_ERR_COUNT_FOLLOWS_NOTHING, + REG_ERR_TRAILING_BACKSLASH, + REG_ERR_CORRUPTED, + REG_ERR_NULL_CHAR, + REG_ERR_NUM +}; + +int regcomp(regex_t *preg, const char *regex, int cflags); +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); +void regfree(regex_t *preg); + +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/jimsh.c b/android/external/usb_modeswitch/usb_modeswitch/jim/jimsh.c new file mode 100755 index 0000000..2c94468 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/jimsh.c @@ -0,0 +1,111 @@ + +/* Jimsh - An interactive shell for Jim + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2009 Steve Bennett <steveb@workware.net.au> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" + +/* From initjimsh.tcl */ +extern int Jim_initjimshInit(Jim_Interp *interp); + +static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) +{ + int n; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + /* Populate argv global var */ + for (n = 0; n < argc; n++) { + Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); + + Jim_ListAppendElement(interp, listObj, obj); + } + + Jim_SetVariableStr(interp, "argv", listObj); + Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); +} + +int main(int argc, char *const argv[]) +{ + int retcode; + Jim_Interp *interp; + + if (argc > 1 && strcmp(argv[1], "--version") == 0) { + printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); + return 0; + } + + /* Create and initialize the interpreter */ + interp = Jim_CreateInterp(); + Jim_RegisterCoreCommands(interp); + + /* Register static extensions */ + if (Jim_InitStaticExtensions(interp) != JIM_OK) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + + Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); + retcode = Jim_initjimshInit(interp); + + if (argc == 1) { + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + if (retcode != JIM_EXIT) { + JimSetArgv(interp, 0, NULL); + retcode = Jim_InteractivePrompt(interp); + } + } + else { + if (argc > 2 && strcmp(argv[1], "-e") == 0) { + JimSetArgv(interp, argc - 3, argv + 3); + retcode = Jim_Eval(interp, argv[2]); + if (retcode != JIM_ERR) { + printf("%s\n", Jim_String(Jim_GetResult(interp))); + } + } + else { + Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); + JimSetArgv(interp, argc - 2, argv + 2); + retcode = Jim_EvalFile(interp, argv[1]); + } + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + } + if (retcode == JIM_EXIT) { + retcode = Jim_GetExitCode(interp); + } + else if (retcode == JIM_ERR) { + retcode = 1; + } + else { + retcode = 0; + } + Jim_FreeInterp(interp); + return retcode; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.c b/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.c new file mode 100755 index 0000000..4065d06 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.c @@ -0,0 +1,1379 @@ +/* linenoise.c -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * You can find the latest source code at: + * + * http://github.com/antirez/linenoise + * + * Does a number of crazy assumptions that happen to be true in 99.9999% of + * the 2010 UNIX computers around. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------------------------ + * + * References: + * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html + * + * Todo list: + * - Win32 support + * - Save and load history containing newlines + * + * Bloat: + * - Completion? + * + * List of escape sequences used by this program, we do everything just + * a few sequences. In order to be so cheap we may have some + * flickering effect with some slow terminal, but the lesser sequences + * the more compatible. + * + * CHA (Cursor Horizontal Absolute) + * Sequence: ESC [ n G + * Effect: moves cursor to column n (1 based) + * + * EL (Erase Line) + * Sequence: ESC [ n K + * Effect: if n is 0 or missing, clear from cursor to end of line + * Effect: if n is 1, clear from beginning of line to cursor + * Effect: if n is 2, clear entire line + * + * CUF (CUrsor Forward) + * Sequence: ESC [ n C + * Effect: moves cursor forward of n chars + * + * The following are used to clear the screen: ESC [ H ESC [ 2 J + * This is actually composed of two sequences: + * + * cursorhome + * Sequence: ESC [ H + * Effect: moves the cursor to upper left corner + * + * ED2 (Clear entire screen) + * Sequence: ESC [ 2 J + * Effect: clear the whole screen + * + * == For highlighting control characters, we also use the following two == + * SO (enter StandOut) + * Sequence: ESC [ 7 m + * Effect: Uses some standout mode such as reverse video + * + * SE (Standout End) + * Sequence: ESC [ 0 m + * Effect: Exit standout mode + * + * == Only used if TIOCGWINSZ fails == + * DSR/CPR (Report cursor position) + * Sequence: ESC [ 6 n + * Effect: reports current cursor position as ESC [ NNN ; MMM R + */ + +#ifdef __MINGW32__ +#include <windows.h> +#include <fcntl.h> +#define USE_WINCONSOLE +#else +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#define USE_TERMIOS +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +#include "linenoise.h" + +#include "jim-config.h" +#ifdef JIM_UTF8 +#define USE_UTF8 +#endif +#include "utf8.h" + +#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 +#define LINENOISE_MAX_LINE 4096 + +#define ctrl(C) ((C) - '@') + +/* Use -ve numbers here to co-exist with normal unicode chars */ +enum { + SPECIAL_NONE, + SPECIAL_UP = -20, + SPECIAL_DOWN = -21, + SPECIAL_LEFT = -22, + SPECIAL_RIGHT = -23, + SPECIAL_DELETE = -24, + SPECIAL_HOME = -25, + SPECIAL_END = -26, +}; + +static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; +static int history_len = 0; +static char **history = NULL; + +/* Structure to contain the status of the current (being edited) line */ +struct current { + char *buf; /* Current buffer. Always null terminated */ + int bufmax; /* Size of the buffer, including space for the null termination */ + int len; /* Number of bytes in 'buf' */ + int chars; /* Number of chars in 'buf' (utf-8 chars) */ + int pos; /* Cursor position, measured in chars */ + int cols; /* Size of the window, in chars */ + const char *prompt; +#if defined(USE_TERMIOS) + int fd; /* Terminal fd */ +#elif defined(USE_WINCONSOLE) + HANDLE outh; /* Console output handle */ + HANDLE inh; /* Console input handle */ + int rows; /* Screen rows */ + int x; /* Current column during output */ + int y; /* Current row */ +#endif +}; + +static int fd_read(struct current *current); +static int getWindowSize(struct current *current); + +void linenoiseHistoryFree(void) { + if (history) { + int j; + + for (j = 0; j < history_len; j++) + free(history[j]); + free(history); + history = NULL; + } +} + +#if defined(USE_TERMIOS) +static void linenoiseAtExit(void); +static struct termios orig_termios; /* in order to restore at exit */ +static int rawmode = 0; /* for atexit() function to check if restore is needed*/ +static int atexit_registered = 0; /* register atexit just 1 time */ + +static const char *unsupported_term[] = {"dumb","cons25",NULL}; + +static int isUnsupportedTerm(void) { + char *term = getenv("TERM"); + + if (term) { + int j; + for (j = 0; unsupported_term[j]; j++) { + if (strcasecmp(term, unsupported_term[j]) == 0) { + return 1; + } + } + } + return 0; +} + +static int enableRawMode(struct current *current) { + struct termios raw; + + current->fd = STDIN_FILENO; + + if (!isatty(current->fd) || isUnsupportedTerm() || + tcgetattr(current->fd, &orig_termios) == -1) { +fatal: + errno = ENOTTY; + return -1; + } + + if (!atexit_registered) { + atexit(linenoiseAtExit); + atexit_registered = 1; + } + + raw = orig_termios; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + /* output modes - disable post processing */ + raw.c_oflag &= ~(OPOST); + /* control modes - set 8 bit chars */ + raw.c_cflag |= (CS8); + /* local modes - choing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) { + goto fatal; + } + rawmode = 1; + + current->cols = 0; + return 0; +} + +static void disableRawMode(struct current *current) { + /* Don't even check the return value as it's too late. */ + if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1) + rawmode = 0; +} + +/* At exit we'll try to fix the terminal to the initial conditions. */ +static void linenoiseAtExit(void) { + if (rawmode) { + tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios); + } + linenoiseHistoryFree(); +} + +/* gcc/glibc insists that we care about the return code of write! */ +#define IGNORE_RC(EXPR) if (EXPR) {} + +/* This is fdprintf() on some systems, but use a different + * name to avoid conflicts + */ +static void fd_printf(int fd, const char *format, ...) +{ + va_list args; + char buf[64]; + int n; + + va_start(args, format); + n = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + IGNORE_RC(write(fd, buf, n)); +} + +static void clearScreen(struct current *current) +{ + fd_printf(current->fd, "\x1b[H\x1b[2J"); +} + +static void cursorToLeft(struct current *current) +{ + fd_printf(current->fd, "\x1b[1G"); +} + +static int outputChars(struct current *current, const char *buf, int len) +{ + return write(current->fd, buf, len); +} + +static void outputControlChar(struct current *current, char ch) +{ + fd_printf(current->fd, "\033[7m^%c\033[0m", ch); +} + +static void eraseEol(struct current *current) +{ + fd_printf(current->fd, "\x1b[0K"); +} + +static void setCursorPos(struct current *current, int x) +{ + fd_printf(current->fd, "\x1b[1G\x1b[%dC", x); +} + +/** + * Reads a char from 'fd', waiting at most 'timeout' milliseconds. + * + * A timeout of -1 means to wait forever. + * + * Returns -1 if no char is received within the time or an error occurs. + */ +static int fd_read_char(int fd, int timeout) +{ + struct pollfd p; + unsigned char c; + + p.fd = fd; + p.events = POLLIN; + + if (poll(&p, 1, timeout) == 0) { + /* timeout */ + return -1; + } + if (read(fd, &c, 1) != 1) { + return -1; + } + return c; +} + +/** + * Reads a complete utf-8 character + * and returns the unicode value, or -1 on error. + */ +static int fd_read(struct current *current) +{ +#ifdef USE_UTF8 + char buf[4]; + int n; + int i; + int c; + + if (read(current->fd, &buf[0], 1) != 1) { + return -1; + } + n = utf8_charlen(buf[0]); + if (n < 1 || n > 3) { + return -1; + } + for (i = 1; i < n; i++) { + if (read(current->fd, &buf[i], 1) != 1) { + return -1; + } + } + buf[n] = 0; + /* decode and return the character */ + utf8_tounicode(buf, &c); + return c; +#else + return fd_read_char(current->fd, -1); +#endif +} + +static int getWindowSize(struct current *current) +{ + struct winsize ws; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) { + current->cols = ws.ws_col; + return 0; + } + + /* Failed to query the window size. Perhaps we are on a serial terminal. + * Try to query the width by sending the cursor as far to the right + * and reading back the cursor position. + * Note that this is only done once per call to linenoise rather than + * every time the line is refreshed for efficiency reasons. + */ + if (current->cols == 0) { + current->cols = 80; + + /* Move cursor far right and report cursor position */ + fd_printf(current->fd, "\x1b[999G" "\x1b[6n"); + + /* Parse the response: ESC [ rows ; cols R */ + if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') { + int n = 0; + while (1) { + int ch = fd_read_char(current->fd, 100); + if (ch == ';') { + /* Ignore rows */ + n = 0; + } + else if (ch == 'R') { + /* Got cols */ + if (n != 0 && n < 1000) { + current->cols = n; + } + break; + } + else if (ch >= 0 && ch <= '9') { + n = n * 10 + ch - '0'; + } + else { + break; + } + } + } + } + return 0; +} + +/** + * If escape (27) was received, reads subsequent + * chars to determine if this is a known special key. + * + * Returns SPECIAL_NONE if unrecognised, or -1 if EOF. + * + * If no additional char is received within a short time, + * 27 is returned. + */ +static int check_special(int fd) +{ + int c = fd_read_char(fd, 50); + int c2; + + if (c < 0) { + return 27; + } + + c2 = fd_read_char(fd, 50); + if (c2 < 0) { + return c2; + } + if (c == '[' || c == 'O') { + /* Potential arrow key */ + switch (c2) { + case 'A': + return SPECIAL_UP; + case 'B': + return SPECIAL_DOWN; + case 'C': + return SPECIAL_RIGHT; + case 'D': + return SPECIAL_LEFT; + case 'F': + return SPECIAL_END; + case 'H': + return SPECIAL_HOME; + } + } + if (c == '[' && c2 >= '1' && c2 <= '6') { + /* extended escape */ + int c3 = fd_read_char(fd, 50); + if (c2 == '3' && c3 == '~') { + /* delete char under cursor */ + return SPECIAL_DELETE; + } + while (c3 != -1 && c3 != '~') { + /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */ + c3 = fd_read_char(fd, 50); + } + } + + return SPECIAL_NONE; +} +#elif defined(USE_WINCONSOLE) + +static DWORD orig_consolemode = 0; + +static int enableRawMode(struct current *current) { + DWORD n; + INPUT_RECORD irec; + + current->outh = GetStdHandle(STD_OUTPUT_HANDLE); + current->inh = GetStdHandle(STD_INPUT_HANDLE); + + if (!PeekConsoleInput(current->inh, &irec, 1, &n)) { + return -1; + } + if (getWindowSize(current) != 0) { + return -1; + } + if (GetConsoleMode(current->inh, &orig_consolemode)) { + SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT); + } + return 0; +} + +static void disableRawMode(struct current *current) +{ + SetConsoleMode(current->inh, orig_consolemode); +} + +static void clearScreen(struct current *current) +{ + COORD topleft = { 0, 0 }; + DWORD n; + + FillConsoleOutputCharacter(current->outh, ' ', + current->cols * current->rows, topleft, &n); + FillConsoleOutputAttribute(current->outh, + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, + current->cols * current->rows, topleft, &n); + SetConsoleCursorPosition(current->outh, topleft); +} + +static void cursorToLeft(struct current *current) +{ + COORD pos = { 0, current->y }; + DWORD n; + + FillConsoleOutputAttribute(current->outh, + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n); + current->x = 0; +} + +static int outputChars(struct current *current, const char *buf, int len) +{ + COORD pos = { current->x, current->y }; + WriteConsoleOutputCharacter(current->outh, buf, len, pos, 0); + current->x += len; + return 0; +} + +static void outputControlChar(struct current *current, char ch) +{ + COORD pos = { current->x, current->y }; + DWORD n; + + FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n); + outputChars(current, "^", 1); + outputChars(current, &ch, 1); +} + +static void eraseEol(struct current *current) +{ + COORD pos = { current->x, current->y }; + DWORD n; + + FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n); +} + +static void setCursorPos(struct current *current, int x) +{ + COORD pos = { x, current->y }; + + SetConsoleCursorPosition(current->outh, pos); + current->x = x; +} + +static int fd_read(struct current *current) +{ + while (1) { + INPUT_RECORD irec; + DWORD n; + if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) { + break; + } + if (!ReadConsoleInput (current->inh, &irec, 1, &n)) { + break; + } + if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown) { + KEY_EVENT_RECORD *k = &irec.Event.KeyEvent; + if (k->dwControlKeyState & ENHANCED_KEY) { + switch (k->wVirtualKeyCode) { + case VK_LEFT: + return SPECIAL_LEFT; + case VK_RIGHT: + return SPECIAL_RIGHT; + case VK_UP: + return SPECIAL_UP; + case VK_DOWN: + return SPECIAL_DOWN; + case VK_DELETE: + return SPECIAL_DELETE; + case VK_HOME: + return SPECIAL_HOME; + case VK_END: + return SPECIAL_END; + } + } + /* Note that control characters are already translated in AsciiChar */ + else { +#ifdef USE_UTF8 + return k->uChar.UnicodeChar; +#else + return k->uChar.AsciiChar; +#endif + } + } + } + return -1; +} + +static int getWindowSize(struct current *current) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(current->outh, &info)) { + return -1; + } + current->cols = info.dwSize.X; + current->rows = info.dwSize.Y; + if (current->cols <= 0 || current->rows <= 0) { + current->cols = 80; + return -1; + } + current->y = info.dwCursorPosition.Y; + current->x = info.dwCursorPosition.X; + return 0; +} +#endif + +static int utf8_getchars(char *buf, int c) +{ +#ifdef USE_UTF8 + return utf8_fromunicode(buf, c); +#else + *buf = c; + return 1; +#endif +} + +/** + * Returns the unicode character at the given offset, + * or -1 if none. + */ +static int get_char(struct current *current, int pos) +{ + if (pos >= 0 && pos < current->chars) { + int c; + int i = utf8_index(current->buf, pos); + (void)utf8_tounicode(current->buf + i, &c); + return c; + } + return -1; +} + +static void refreshLine(const char *prompt, struct current *current) +{ + int plen; + int pchars; + int backup = 0; + int i; + const char *buf = current->buf; + int chars = current->chars; + int pos = current->pos; + int b; + int ch; + int n; + + /* Should intercept SIGWINCH. For now, just get the size every time */ + getWindowSize(current); + + plen = strlen(prompt); + pchars = utf8_strlen(prompt, plen); + + /* Account for a line which is too long to fit in the window. + * Note that control chars require an extra column + */ + + /* How many cols are required to the left of 'pos'? + * The prompt, plus one extra for each control char + */ + n = pchars + utf8_strlen(buf, current->len); + b = 0; + for (i = 0; i < pos; i++) { + b += utf8_tounicode(buf + b, &ch); + if (ch < ' ') { + n++; + } + } + + /* If too many are need, strip chars off the front of 'buf' + * until it fits. Note that if the current char is a control character, + * we need one extra col. + */ + if (current->pos < current->chars && get_char(current, current->pos) < ' ') { + n++; + } + + while (n >= current->cols) { + b = utf8_tounicode(buf, &ch); + if (ch < ' ') { + n--; + } + n--; + buf += b; + pos--; + chars--; + } + + /* Cursor to left edge, then the prompt */ + cursorToLeft(current); + outputChars(current, prompt, plen); + + /* Now the current buffer content */ + + /* Need special handling for control characters. + * If we hit 'cols', stop. + */ + b = 0; /* unwritted bytes */ + n = 0; /* How many control chars were written */ + for (i = 0; i < chars; i++) { + int ch; + int w = utf8_tounicode(buf + b, &ch); + if (ch < ' ') { + n++; + } + if (pchars + i + n >= current->cols) { + break; + } + if (ch < ' ') { + /* A control character, so write the buffer so far */ + outputChars(current, buf, b); + buf += b + w; + b = 0; + outputControlChar(current, ch + '@'); + if (i < pos) { + backup++; + } + } + else { + b += w; + } + } + outputChars(current, buf, b); + + /* Erase to right, move cursor to original position */ + eraseEol(current); + setCursorPos(current, pos + pchars + backup); +} + +static void set_current(struct current *current, const char *str) +{ + strncpy(current->buf, str, current->bufmax); + current->buf[current->bufmax - 1] = 0; + current->len = strlen(current->buf); + current->pos = current->chars = utf8_strlen(current->buf, current->len); +} + +static int has_room(struct current *current, int bytes) +{ + return current->len + bytes < current->bufmax - 1; +} + +/** + * Removes the char at 'pos'. + * + * Returns 1 if the line needs to be refreshed, 2 if not + * and 0 if nothing was removed + */ +static int remove_char(struct current *current, int pos) +{ + if (pos >= 0 && pos < current->chars) { + int p1, p2; + int ret = 1; + p1 = utf8_index(current->buf, pos); + p2 = p1 + utf8_index(current->buf + p1, 1); + +#ifdef USE_TERMIOS + /* optimise remove char in the case of removing the last char */ + if (current->pos == pos + 1 && current->pos == current->chars) { + if (current->buf[pos] >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { + ret = 2; + fd_printf(current->fd, "\b \b"); + } + } +#endif + + /* Move the null char too */ + memmove(current->buf + p1, current->buf + p2, current->len - p2 + 1); + current->len -= (p2 - p1); + current->chars--; + + if (current->pos > pos) { + current->pos--; + } + return ret; + } + return 0; +} + +/** + * Insert 'ch' at position 'pos' + * + * Returns 1 if the line needs to be refreshed, 2 if not + * and 0 if nothing was inserted (no room) + */ +static int insert_char(struct current *current, int pos, int ch) +{ + char buf[3]; + int n = utf8_getchars(buf, ch); + + if (has_room(current, n) && pos >= 0 && pos <= current->chars) { + int p1, p2; + int ret = 1; + p1 = utf8_index(current->buf, pos); + p2 = p1 + n; + +#ifdef USE_TERMIOS + /* optimise the case where adding a single char to the end and no scrolling is needed */ + if (current->pos == pos && current->chars == pos) { + if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { + IGNORE_RC(write(current->fd, buf, n)); + ret = 2; + } + } +#endif + + memmove(current->buf + p2, current->buf + p1, current->len - p1); + memcpy(current->buf + p1, buf, n); + current->len += n; + + current->chars++; + if (current->pos >= pos) { + current->pos++; + } + return ret; + } + return 0; +} + +/** + * Returns 0 if no chars were removed or non-zero otherwise. + */ +static int remove_chars(struct current *current, int pos, int n) +{ + int removed = 0; + while (n-- && remove_char(current, pos)) { + removed++; + } + return removed; +} + +#ifndef NO_COMPLETION +static linenoiseCompletionCallback *completionCallback = NULL; + +static void beep() { +#ifdef USE_TERMIOS + fprintf(stderr, "\x7"); + fflush(stderr); +#endif +} + +static void freeCompletions(linenoiseCompletions *lc) { + size_t i; + for (i = 0; i < lc->len; i++) + free(lc->cvec[i]); + free(lc->cvec); +} + +static int completeLine(struct current *current) { + linenoiseCompletions lc = { 0, NULL }; + int c = 0; + + completionCallback(current->buf,&lc); + if (lc.len == 0) { + beep(); + } else { + size_t stop = 0, i = 0; + + while(!stop) { + /* Show completion or original buffer */ + if (i < lc.len) { + struct current tmp = *current; + tmp.buf = lc.cvec[i]; + tmp.pos = tmp.len = strlen(tmp.buf); + tmp.chars = utf8_strlen(tmp.buf, tmp.len); + refreshLine(current->prompt, &tmp); + } else { + refreshLine(current->prompt, current); + } + + c = fd_read(current); + if (c == -1) { + break; + } + + switch(c) { + case '\t': /* tab */ + i = (i+1) % (lc.len+1); + if (i == lc.len) beep(); + break; + case 27: /* escape */ + /* Re-show original buffer */ + if (i < lc.len) { + refreshLine(current->prompt, current); + } + stop = 1; + break; + default: + /* Update buffer and return */ + if (i < lc.len) { + set_current(current,lc.cvec[i]); + } + stop = 1; + break; + } + } + } + + freeCompletions(&lc); + return c; /* Return last read character */ +} + +/* Register a callback function to be called for tab-completion. */ +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { + completionCallback = fn; +} + +void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { + lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1)); + lc->cvec[lc->len++] = strdup(str); +} + +#endif + +static int linenoisePrompt(struct current *current) { + int history_index = 0; + + /* The latest history entry is always our current buffer, that + * initially is just an empty string. */ + linenoiseHistoryAdd(""); + + set_current(current, ""); + refreshLine(current->prompt, current); + + while(1) { + int dir = -1; + int c = fd_read(current); + +#ifndef NO_COMPLETION + /* Only autocomplete when the callback is set. It returns < 0 when + * there was an error reading from fd. Otherwise it will return the + * character that should be handled next. */ + if (c == 9 && completionCallback != NULL) { + c = completeLine(current); + /* Return on errors */ + if (c < 0) return current->len; + /* Read next character when 0 */ + if (c == 0) continue; + } +#endif + +process_char: + if (c == -1) return current->len; +#ifdef USE_TERMIOS + if (c == 27) { /* escape sequence */ + c = check_special(current->fd); + } +#endif + switch(c) { + case '\r': /* enter */ + history_len--; + free(history[history_len]); + return current->len; + case ctrl('C'): /* ctrl-c */ + errno = EAGAIN; + return -1; + case 127: /* backspace */ + case ctrl('H'): + if (remove_char(current, current->pos - 1) == 1) { + refreshLine(current->prompt, current); + } + break; + case ctrl('D'): /* ctrl-d */ + if (current->len == 0) { + /* Empty line, so EOF */ + history_len--; + free(history[history_len]); + return -1; + } + /* Otherwise delete char to right of cursor */ + if (remove_char(current, current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('W'): /* ctrl-w */ + /* eat any spaces on the left */ + { + int pos = current->pos; + while (pos > 0 && get_char(current, pos - 1) == ' ') { + pos--; + } + + /* now eat any non-spaces on the left */ + while (pos > 0 && get_char(current, pos - 1) != ' ') { + pos--; + } + + if (remove_chars(current, pos, current->pos - pos)) { + refreshLine(current->prompt, current); + } + } + break; + case ctrl('R'): /* ctrl-r */ + { + /* Display the reverse-i-search prompt and process chars */ + char rbuf[50]; + char rprompt[80]; + int rchars = 0; + int rlen = 0; + int searchpos = history_len - 1; + + rbuf[0] = 0; + while (1) { + int n = 0; + const char *p = NULL; + int skipsame = 0; + int searchdir = -1; + + snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf); + refreshLine(rprompt, current); + c = fd_read(current); + if (c == ctrl('H') || c == 127) { + if (rchars) { + int p = utf8_index(rbuf, --rchars); + rbuf[p] = 0; + rlen = strlen(rbuf); + } + continue; + } +#ifdef USE_TERMIOS + if (c == 27) { + c = check_special(current->fd); + } +#endif + if (c == ctrl('P') || c == SPECIAL_UP) { + /* Search for the previous (earlier) match */ + if (searchpos > 0) { + searchpos--; + } + skipsame = 1; + } + else if (c == ctrl('N') || c == SPECIAL_DOWN) { + /* Search for the next (later) match */ + if (searchpos < history_len) { + searchpos++; + } + searchdir = 1; + skipsame = 1; + } + else if (c >= ' ') { + if (rlen >= (int)sizeof(rbuf) + 3) { + continue; + } + + n = utf8_getchars(rbuf + rlen, c); + rlen += n; + rchars++; + rbuf[rlen] = 0; + + /* Adding a new char resets the search location */ + searchpos = history_len - 1; + } + else { + /* Exit from incremental search mode */ + break; + } + + /* Now search through the history for a match */ + for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) { + p = strstr(history[searchpos], rbuf); + if (p) { + /* Found a match */ + if (skipsame && strcmp(history[searchpos], current->buf) == 0) { + /* But it is identical, so skip it */ + continue; + } + /* Copy the matching line and set the cursor position */ + set_current(current,history[searchpos]); + current->pos = utf8_strlen(history[searchpos], p - history[searchpos]); + break; + } + } + if (!p && n) { + /* No match, so don't add it */ + rchars--; + rlen -= n; + rbuf[rlen] = 0; + } + } + if (c == ctrl('G') || c == ctrl('C')) { + /* ctrl-g terminates the search with no effect */ + set_current(current, ""); + c = 0; + } + else if (c == ctrl('J')) { + /* ctrl-j terminates the search leaving the buffer in place */ + c = 0; + } + /* Go process the char normally */ + refreshLine(current->prompt, current); + goto process_char; + } + break; + case ctrl('T'): /* ctrl-t */ + if (current->pos > 0 && current->pos < current->chars) { + c = get_char(current, current->pos); + remove_char(current, current->pos); + insert_char(current, current->pos - 1, c); + refreshLine(current->prompt, current); + } + break; + case ctrl('V'): /* ctrl-v */ + if (has_room(current, 3)) { + /* Insert the ^V first */ + if (insert_char(current, current->pos, c)) { + refreshLine(current->prompt, current); + /* Now wait for the next char. Can insert anything except \0 */ + c = fd_read(current); + + /* Remove the ^V first */ + remove_char(current, current->pos - 1); + if (c != -1) { + /* Insert the actual char */ + insert_char(current, current->pos, c); + } + refreshLine(current->prompt, current); + } + } + break; + case ctrl('B'): + case SPECIAL_LEFT: + if (current->pos > 0) { + current->pos--; + refreshLine(current->prompt, current); + } + break; + case ctrl('F'): + case SPECIAL_RIGHT: + if (current->pos < current->chars) { + current->pos++; + refreshLine(current->prompt, current); + } + break; + case ctrl('P'): + case SPECIAL_UP: + dir = 1; + case ctrl('N'): + case SPECIAL_DOWN: + if (history_len > 1) { + /* Update the current history entry before to + * overwrite it with tne next one. */ + free(history[history_len-1-history_index]); + history[history_len-1-history_index] = strdup(current->buf); + /* Show the new entry */ + history_index += dir; + if (history_index < 0) { + history_index = 0; + break; + } else if (history_index >= history_len) { + history_index = history_len-1; + break; + } + set_current(current, history[history_len-1-history_index]); + refreshLine(current->prompt, current); + } + break; + + case SPECIAL_DELETE: + if (remove_char(current, current->pos) == 1) { + refreshLine(current->prompt, current); + } + break; + case SPECIAL_HOME: + current->pos = 0; + refreshLine(current->prompt, current); + break; + case SPECIAL_END: + current->pos = current->chars; + refreshLine(current->prompt, current); + break; + default: + /* Only tab is allowed without ^V */ + if (c == '\t' || c >= ' ') { + if (insert_char(current, current->pos, c) == 1) { + refreshLine(current->prompt, current); + } + } + break; + case ctrl('U'): /* Ctrl+u, delete to beginning of line. */ + if (remove_chars(current, 0, current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('K'): /* Ctrl+k, delete from current to end of line. */ + if (remove_chars(current, current->pos, current->chars - current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('A'): /* Ctrl+a, go to the start of the line */ + current->pos = 0; + refreshLine(current->prompt, current); + break; + case ctrl('E'): /* ctrl+e, go to the end of the line */ + current->pos = current->chars; + refreshLine(current->prompt, current); + break; + case ctrl('L'): /* Ctrl+L, clear screen */ + /* clear screen */ + clearScreen(current); + /* Force recalc of window size for serial terminals */ + current->cols = 0; + refreshLine(current->prompt, current); + break; + } + } + return current->len; +} + +char *linenoise(const char *prompt) +{ + int count; + struct current current; + char buf[LINENOISE_MAX_LINE]; + + if (enableRawMode(¤t) == -1) { + printf("%s", prompt); + fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + return NULL; + } + count = strlen(buf); + if (count && buf[count-1] == '\n') { + count--; + buf[count] = '\0'; + } + } + else + { + current.buf = buf; + current.bufmax = sizeof(buf); + current.len = 0; + current.chars = 0; + current.pos = 0; + current.prompt = prompt; + + count = linenoisePrompt(¤t); + disableRawMode(¤t); + printf("\n"); + if (count == -1) { + return NULL; + } + } + return strdup(buf); +} + +/* Using a circular buffer is smarter, but a bit more complex to handle. */ +int linenoiseHistoryAdd(const char *line) { + char *linecopy; + + if (history_max_len == 0) return 0; + if (history == NULL) { + history = (char**)malloc(sizeof(char*)*history_max_len); + if (history == NULL) return 0; + memset(history,0,(sizeof(char*)*history_max_len)); + } + linecopy = strdup(line); + if (!linecopy) return 0; + if (history_len == history_max_len) { + free(history[0]); + memmove(history,history+1,sizeof(char*)*(history_max_len-1)); + history_len--; + } + history[history_len] = linecopy; + history_len++; + return 1; +} + +int linenoiseHistorySetMaxLen(int len) { + char **newHistory; + + if (len < 1) return 0; + if (history) { + int tocopy = history_len; + + newHistory = (char**)malloc(sizeof(char*)*len); + if (newHistory == NULL) return 0; + if (len < tocopy) tocopy = len; + memcpy(newHistory,history+(history_max_len-tocopy), sizeof(char*)*tocopy); + free(history); + history = newHistory; + } + history_max_len = len; + if (history_len > history_max_len) + history_len = history_max_len; + return 1; +} + +/* Save the history in the specified file. On success 0 is returned + * otherwise -1 is returned. */ +int linenoiseHistorySave(const char *filename) { + FILE *fp = fopen(filename,"w"); + int j; + + if (fp == NULL) return -1; + for (j = 0; j < history_len; j++) { + const char *str = history[j]; + /* Need to encode backslash, nl and cr */ + while (*str) { + if (*str == '\\') { + fputs("\\\\", fp); + } + else if (*str == '\n') { + fputs("\\n", fp); + } + else if (*str == '\r') { + fputs("\\r", fp); + } + else { + fputc(*str, fp); + } + str++; + } + fputc('\n', fp); + } + + fclose(fp); + return 0; +} + +/* Load the history from the specified file. If the file does not exist + * zero is returned and no operation is performed. + * + * If the file exists and the operation succeeded 0 is returned, otherwise + * on error -1 is returned. */ +int linenoiseHistoryLoad(const char *filename) { + FILE *fp = fopen(filename,"r"); + char buf[LINENOISE_MAX_LINE]; + + if (fp == NULL) return -1; + + while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { + char *src, *dest; + + /* Decode backslash escaped values */ + for (src = dest = buf; *src; src++) { + char ch = *src; + + if (ch == '\\') { + src++; + if (*src == 'n') { + ch = '\n'; + } + else if (*src == 'r') { + ch = '\r'; + } else { + ch = *src; + } + } + *dest++ = ch; + } + /* Remove trailing newline */ + if (dest != buf && (dest[-1] == '\n' || dest[-1] == '\r')) { + dest--; + } + *dest = 0; + + linenoiseHistoryAdd(buf); + } + fclose(fp); + return 0; +} + +/* Provide access to the history buffer. + * + * If 'len' is not NULL, the length is stored in *len. + */ +char **linenoiseHistory(int *len) { + if (len) { + *len = history_len; + } + return history; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.h b/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.h new file mode 100755 index 0000000..dcf22f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/linenoise.h @@ -0,0 +1,62 @@ +/* linenoise.h -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * See linenoise.c for more information. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINENOISE_H +#define __LINENOISE_H + +/* Currently never enable completion */ +#define NO_COMPLETION + +#ifndef NO_COMPLETION +typedef struct linenoiseCompletions { + size_t len; + char **cvec; +} linenoiseCompletions; + +typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); +void linenoiseAddCompletion(linenoiseCompletions *, const char *); +#endif + +char *linenoise(const char *prompt); +int linenoiseHistoryAdd(const char *line); +int linenoiseHistorySetMaxLen(int len); +int linenoiseHistorySave(const char *filename); +int linenoiseHistoryLoad(const char *filename); +void linenoiseHistoryFree(void); +char **linenoiseHistory(int *len); + +#endif /* __LINENOISE_H */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim b/android/external/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim new file mode 100755 index 0000000..cc2cd5d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim @@ -0,0 +1,104 @@ +#!/bin/sh + +# This script writes to stdout, a single source file (e.g. jimsh0.c) +# which can be compiled to provide a bootstrap version of jimsh. +# e.g. cc -o jimsh0 jimsh0.c + +makeext() +{ + source="$1" + basename=`basename "$source" .tcl` +cat <<EOF +int Jim_${basename}Init(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "$basename", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "$source", 1, +EOF + +# Note: Keep newlines so that line numbers match in error messages +sed -e 's/^[ ]*#.*//' -e 's@\\@\\\\@g' -e 's@"@\\"@g' -e 's@^\(.*\)$@"\1\\n"@' $source + +echo ");" +echo "}" +} + +makeloadexts() +{ +cat <<EOF +int Jim_InitStaticExtensions(Jim_Interp *interp) +EOF + echo "{" + for ext in $*; do + echo "extern int Jim_${ext}Init(Jim_Interp *);" + done + for ext in $*; do + echo "Jim_${ext}Init(interp);" + done + echo "return JIM_OK;" + echo "}" +} + +cexts="aio readdir regexp file exec clock array" +tclexts="bootstrap initjimsh glob stdlib tclcompat" + +# Note ordering +allexts="bootstrap aio readdir glob regexp file exec clock array stdlib tclcompat" + +echo "/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */" + +# define some core features +for i in _GNU_SOURCE JIM_TCL_COMPAT JIM_REFERENCES JIM_ANSIC JIM_REGEXP HAVE_NO_AUTOCONF _JIMAUTOCONF_H; do + echo "#define $i" +done +echo '#define TCL_LIBRARY "."' +# and extensions +for i in $allexts; do + echo "#define jim_ext_$i" +done + +# Can we make a bootstrap jimsh work even on mingw32? +cat <<EOF +#if defined(__MINGW32__) +#define TCL_PLATFORM_OS "mingw" +#define TCL_PLATFORM_PLATFORM "windows" +#define TCL_PLATFORM_PATH_SEPARATOR ";" +#define HAVE_MKDIR_ONE_ARG +#define HAVE_SYSTEM +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#else +#define TCL_PLATFORM_OS "unknown" +#define TCL_PLATFORM_PLATFORM "unix" +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#define HAVE_VFORK +#define HAVE_WAITPID +#endif +EOF + +outputsource() +{ + sed -e '/#include.*jim/d' -e '/#include.*utf8/d' \ + -e '/^#.*if.*JIM_BOOTSTRAP/,/^#endif.*JIM_BOOTSTRAP/d' \ + -e 's/\/\*.*\*\///' -e '/^[ ]*\/\*/,/\*\//d' $1 +} + +# Now output header files, removing references to jim header files +for i in utf8.h jim.h jim-subcmd.h jimregexp.h ; do + outputsource $i +done + +# Now extension source code +for i in $tclexts; do + makeext $i.tcl +done +for i in $cexts; do + outputsource jim-$i.c +done +makeloadexts $allexts + +# And finally the core source code +for i in jim.c jim-subcmd.c utf8.c jim-interactive.c jim-format.c jimregexp.c jimsh.c; do + outputsource $i +done diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl new file mode 100755 index 0000000..fd1a056 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl @@ -0,0 +1,38 @@ +#!/usr/bin/env tclsh + +# Usage: make-c-ext.tcl source.tcl >jim-source.c + +# Converts a Tcl source file into C source suitable +# for loading as a static extension. + +lassign $argv source + +if {![string match *.tcl $source]} { + error "Source $source is not a .tcl file" +} + +# Read the Tcl source and convert to C +# Note that no lines are removed in order to preserve line numbering +set sourcelines {} +set f [open $source] +while {[gets $f buf] >= 0} { + # Remove comment lines + regsub {^[ \t]*#.*$} $buf "" buf + # Escape quotes and backlashes + set buf [string map [list \\ \\\\ \" \\"] $buf] + lappend sourcelines \"$buf\\n\" +} +close $f + +lappend lines {/* autogenerated - do not edit */} +lappend lines {#include <jim.h>} +set basename [file tail $source] +set pkgname [file rootname $basename] + +lappend lines "int Jim_${pkgname}Init(Jim_Interp *interp)" +lappend lines "\{" +lappend lines "\tif (Jim_PackageProvide(interp, \"$pkgname\", \"1.0\", JIM_ERRMSG)) return JIM_ERR;" +lappend lines "\treturn Jim_EvalSource(interp, \"$basename\", 1, [join $sourcelines \n]);" +lappend lines "\}" + +puts [join $lines \n] diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/make-index b/android/external/usb_modeswitch/usb_modeswitch/jim/make-index new file mode 100755 index 0000000..8dba920 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/make-index @@ -0,0 +1,70 @@ +#!/usr/bin/env tclsh +# vim:se syn=tcl: + +set filename [lindex $argv 0] +set f [open $filename] + +# Read the file looking for command definitions +set lines {} +set commands {} +array set cdict {} +set c 0 + +while {[gets $f buf] >= 0} { + if {[string match "~~*" $buf]} { + if {[string match "*:*" $prev]} { + incr c + set target cmd_$c + set lines [linsert $lines end-1 "\[\[$target\]\]"] + } else { + set target _$prev + } + foreach cmd [split $prev ":,"] { + set cmd [string trim $cmd] + if {[regexp {^[a-z.]+$} $cmd]} { + lappend commands [list $cmd $target] + set cdict($cmd) $target + } + } + } + lappend lines $buf + set prev $buf +} +close $f + +# Build the command index in the list: $index +lappend index {[frame="none",grid="none"]} +lappend index {|=========================} +set i 0 +set row {} +foreach command [lsort $commands] { + lassign $command cmd target + + append row "|<<$target,*`$cmd`*>> " + incr i + if {$i % 8 == 0} { + lappend index $row + set row {} + } +} +while {$i % 8 != 0} { + incr i + append row "| " +} +lappend index $row +lappend index {|=========================} + +# Map all `cmd` to <<$target,`cmd`>> +set mapping {} +foreach c [array names cdict] { + lappend mapping `$c` <<$cdict($c),*`$c`*>> + lappend mapping "`$c " "<<$cdict($c),*`$c`*>> `" +} + +# And the command index +lappend mapping @INSERTINDEX@ [join $index \n] + +# Output the result +foreach line $lines { + puts [string map $mapping $line] +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl new file mode 100755 index 0000000..9185e77 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl @@ -0,0 +1,48 @@ +#!/usr/bin/env tclsh + +# Usage: make-load-static-exts extname ... >load-static-exts.c + +# Creates load-static-exts.c based on the configured static extensions + +# There are some dependencies on static extensions which require +# a certain load order. Do this by setting priorities and sorting. + +array set pri { + stdlib 0 + readdir 1 + glob 2 + oo 1 + tree 2 + pack 1 + binary 2 +} + +foreach i $argv { + set p 1 + if {[info exists pri($i)]} { + set p $pri($i) + } + lappend exts [list $p $i] +} +set exts [lsort $exts] + +puts { +/* autogenerated - do not edit */ +#include "jim.h" +#include "jimautoconf.h" +int Jim_InitStaticExtensions(Jim_Interp *interp) +} +puts \{ + +foreach e $exts { + set ext [lindex $e 1] + puts "\textern int Jim_${ext}Init(Jim_Interp *);" +} +foreach e $exts { + set ext [lindex $e 1] + puts "\tJim_${ext}Init(interp);" +} + +puts "\treturn JIM_OK;" + +puts \} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl new file mode 100755 index 0000000..4b5ec3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl @@ -0,0 +1,64 @@ +#!/usr/bin/env tclsh + +# Generate UTF-8 case mapping tables +# +# (c) 2010 Steve Bennett <steveb@workware.net.au> +# +# See LICENCE for licence details. +#/ + +# Parse the unicode data from: http://unicode.org/Public/UNIDATA/UnicodeData.txt +# to generate case mapping tables + +set f [open [lindex $argv 0]] +set extoff 0 +puts "static const struct casemap unicode_case_mapping\[\] = \{" +while {[gets $f buf] >= 0} { + foreach {code name class x x x x x x x x x upper lower} [split $buf ";"] break + set code 0x$code + if {$code <= 0x7f} { + continue + } + if {$code > 0xffff} { + break + } + if {$class ne "Lu" && $class ne "Ll"} { + continue + } + if {$upper eq ""} { + set upper $code + } else { + set upper 0x$upper + } + if {$lower eq ""} { + set lower $code + } else { + set lower 0x$lower + } + if {$upper == $code && $lower == $code} { + continue + } + set l [expr {$lower - $code}] + set u [expr {$upper - $code}] + if {abs($u) > 127 || abs($l) > 127} { + # Can't encode both in one byte, so use indirection + lappend jumptable $code $lower $upper + set l -128 + set u $extoff + incr extoff + if {$extoff > 0xff} { + error "Too many entries in the offset table!" + } + } + set entry [string tolower "$code, $l, $u"] + puts " { $entry }," +} +close $f +puts "\};\n" + +# Now the jump table +puts "static const struct caseextmap unicode_extmap\[\] = \{" +foreach {c l u} $jumptable { + puts " { $l, $u }," +} +puts "\};\n" diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/regtest.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/regtest.tcl new file mode 100755 index 0000000..de796d9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/regtest.tcl @@ -0,0 +1,158 @@ +# REGTEST 1 +# 27Jan2005 - SIGSEGV for bug on Jim_DuplicateObj(). + +for {set i 0} {$i < 100} {incr i} { + set a "x" + lappend a n +} +puts "TEST 1 PASSED" + +# REGTEST 2 +# 29Jan2005 - SEGFAULT parsing script composed of just one comment. +eval {#foobar} +puts "TEST 2 PASSED" + +# REGTEST 3 +# 29Jan2005 - "Error in Expression" with correct expression +set x 5 +expr {$x-5} +puts "TEST 3 PASSED" + +# REGTEST 4 +# 29Jan2005 - SIGSEGV when run this code, due to expr's bug. +proc fibonacci {x} { + if {$x <= 1} { + expr 1 + } else { + expr {[fibonacci [expr {$x-1}]] + [fibonacci [expr {$x-2}]]} + } +} +fibonacci 6 +puts "TEST 4 PASSED" + +# REGTEST 5 +# 06Mar2005 - This looped forever... +for {set i 0} {$i < 10} {incr i} {continue} +puts "TEST 5 PASSED" + +# REGTEST 6 +# 07Mar2005 - Unset create variable + dict is using dict syntax sugar at +# currently non-existing variable +catch {unset thisvardoesnotexists(thiskeytoo)} +if {[catch {set thisvardoesnotexists}] == 0} { + puts "TEST 6 FAILED - unset created dict for non-existing variable" + break +} +puts "TEST 6 PASSED" + +# REGTEST 7 +# 04Nov2008 - variable parsing does not eat last brace +set a 1 +list ${a} +puts "TEST 7 PASSED" + +# REGTEST 8 +# 04Nov2008 - string toupper/tolower do not convert to string rep +string tolower [list a] +string toupper [list a] +puts "TEST 8 PASSED" + +# REGTEST 9 +# 04Nov2008 - crash on exit when replacing Tcl proc with C command. +# Requires the clock extension to be built as a loadable module. +proc clock {args} {} +catch {package require clock} +# Note, crash on exit, so don't say we passed! + +# REGTEST 10 +# 05Nov2008 - incorrect lazy expression evaluation with unary not +expr {1 || !0} +puts "TEST 10 PASSED" + +# REGTEST 11 +# 14 Feb 2010 - access static variable in deleted proc +proc a {} {{x 1}} { rename a ""; incr x } +a +puts "TEST 11 PASSED" + +# REGTEST 12 +# 13 Sep 2010 - reference with invalid tag +set a b[ref value "tag name"] +getref [string range $a 1 end] +puts "TEST 12 PASSED" + +# REGTEST 13 +# 14 Sep 2010 - parse list with trailing backslash +set x "switch -0 \$on \\" +lindex $x 1 +puts "TEST 13 PASSED" + +# REGTEST 14 +# 14 Sep 2010 - command expands to nothing +eval "{*}{}" +puts "TEST 14 PASSED" + +# REGTEST 15 +# 24 Feb 2010 - bad reference counting of the stack trace in 'error' +proc a {msg stack} { + tailcall error $msg $stack +} +catch {fail} msg opts +catch {a $msg $opts(-errorinfo)} + +# REGTEST 16 +# 24 Feb 2010 - rename the current proc +# Leaves unfreed objects on the stack +proc a {} { rename a newa} +a + +# REGTEST 17 +# 26 Nov 2010 - crashes on invalid dict sugar +catch {eval {$x(}} +puts "TEST 17 PASSED" + +# REGTEST 18 +# 12 Apr 2011 - crashes on unset for loop var +catch { + for {set i 0} {$i < 5} {incr i} {unset i} +} +puts "TEST 18 PASSED" + +# REGTEST 19 +# 25 May 2011 - crashes with double colon +catch { + expr {5 ne ::} +} +puts "TEST 19 PASSED" + +# REGTEST 20 +# 26 May 2011 - infinite recursion +proc a {} { global ::blah; set ::blah test } +a +puts "TEST 20 PASSED" + +# REGTEST 21 +# 26 May 2011 - infinite loop with null byte in subst +subst "abc\0def" +puts "TEST 21 PASSED" + +# REGTEST 22 +# 21 June 2011 - crashes on lappend to to value with script rep +set x rand +eval $x +lappend x b +puts "TEST 22 PASSED" + +# REGTEST 23 +# 27 July 2011 - unfreed objects on exit +catch { + set x abc + subst $x + regexp $x $x +} +# Actually, the test passes if no objects leaked on exit +puts "TEST 23 PASSED" + +# TAKE THE FOLLOWING puts AS LAST LINE + +puts "--- ALL TESTS PASSED ---" diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl new file mode 100755 index 0000000..cdd78d4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl @@ -0,0 +1,45 @@ +# Readline-based interactive shell for Jim +# Copyright(C) 2005 Salvatore Sanfilippo <antirez@invece.org> +# +# In order to automatically have readline-editing features +# put this in your $HOME/.jimrc +# +# if {$jim_interactive} { +# if {[catch {package require rlprompt}] == 0} { +# rlprompt.shell +# } +# } +package require readline + +proc rlprompt.shell {} { + puts "Readline shell loaded" + puts "Welcome to Jim [info version]!" + set prompt ". " + set buf "" + while 1 { + set line [readline.readline $prompt] + + if {[string length $line] == 0} { + continue + } + if {$buf eq ""} { + set buf $line + } else { + append buf \n $line + } + if {![info complete $buf]} { + set prompt "> " + continue + } + readline.addhistory $buf + + catch { + uplevel #0 $buf + } error + if {$error ne ""} { + puts $error + } + set buf "" + set prompt ". " + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl new file mode 100755 index 0000000..3abeb3e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl @@ -0,0 +1,150 @@ +# Create a single word alias (proc) for one or more words +# e.g. alias x info exists +# if {[x var]} ... +proc alias {name args} { + set prefix $args + proc $name args prefix { + tailcall {*}$prefix {*}$args + } +} + +# Creates an anonymous procedure +proc lambda {arglist args} { + set name [ref {} function lambda.finalizer] + tailcall proc $name $arglist {*}$args +} + +proc lambda.finalizer {name val} { + rename $name {} +} + +# Like alias, but creates and returns an anonyous procedure +proc curry {args} { + set prefix $args + lambda args prefix { + tailcall {*}$prefix {*}$args + } +} + +# Returns the given argument. +# Useful with 'local' as follows: +# proc a {} {...} +# local function a +# +# set x [lambda ...] +# local function $x +# +proc function {value} { + return $value +} + +# Tcl 8.5 lassign +proc lassign {list args} { + # in case the list is empty... + lappend list {} + uplevel 1 [list foreach $args $list break] + lrange $list [llength $args] end-1 +} + +# Returns a list of proc filename line ... +# with 3 entries for each stack frame (proc), +# (deepest level first) +proc stacktrace {} { + set trace {} + foreach level [range 1 [info level]] { + lassign [info frame -$level] p f l + lappend trace $p $f $l + } + return $trace +} + +# Returns a human-readable version of a stack trace +proc stackdump {stacktrace} { + set result {} + set count 0 + foreach {l f p} [lreverse $stacktrace] { + if {$count} { + append result \n + } + incr count + if {$p ne ""} { + append result "in procedure '$p' " + if {$f ne ""} { + append result "called " + } + } + if {$f ne ""} { + append result "at file \"$f\", line $l" + } + } + return $result +} + +# Sort of replacement for $::errorInfo +# Usage: errorInfo error ?stacktrace? +proc errorInfo {msg {stacktrace ""}} { + if {$stacktrace eq ""} { + set stacktrace [info stacktrace] + } + lassign $stacktrace p f l + if {$f ne ""} { + set result "Runtime Error: $f:$l: " + } + append result "$msg\n" + append result [stackdump $stacktrace] + + # Remove the trailing newline + string trim $result +} + +# Finds the current executable by searching along the path +# Returns the empty string if not found. +proc {info nameofexecutable} {} { + if {[info exists ::jim_argv0]} { + if {[string match "*/*" $::jim_argv0]} { + return [file join [pwd] $::jim_argv0] + } + foreach path [split [env PATH ""] $::tcl_platform(pathSeparator)] { + set exec [file join [pwd] $path $::jim_argv0] + if {[file executable $exec]} { + return $exec + } + } + } + return "" +} + +# Script-based implementation of 'dict with' +proc {dict with} {dictVar args script} { + upvar $dictVar dict + set keys {} + foreach {n v} [dict get $dict {*}$args] { + upvar $n var_$n + set var_$n $v + lappend keys $n + } + catch {uplevel 1 $script} msg opts + if {[info exists dict] && [dict exists $dict {*}$args]} { + foreach n $keys { + if {[info exists var_$n]} { + dict set dict {*}$args $n [set var_$n] + } else { + dict unset dict {*}$args $n + } + } + } + return {*}$opts $msg +} + +# Script-based implementation of 'dict merge' +# This won't get called in the trivial case of no args +proc {dict merge} {dict args} { + foreach d $args { + # Check for a valid dict + dict size $d + foreach {k v} $d { + dict set dict $k $v + } + } + return $dict +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms b/android/external/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms new file mode 100755 index 0000000..f1dcaa5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms @@ -0,0 +1,40 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl new file mode 100755 index 0000000..8e5b128 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl @@ -0,0 +1,279 @@ +# (c) 2008 Steve Bennett <steveb@workware.net.au> +# +# Loads some Tcl-compatible features. +# I/O commands, case, lassign, parray, errorInfo, ::tcl_platform, ::env +# try, throw, file copy, file delete -force + +# Set up the ::env array +set env [env] + +if {[info commands stdout] ne ""} { + # Tcl-compatible I/O commands + foreach p {gets flush close eof seek tell} { + proc $p {chan args} {p} { + tailcall $chan $p {*}$args + } + } + unset p + + # puts is complicated by -nonewline + # + proc puts {{-nonewline {}} {chan stdout} msg} { + if {${-nonewline} ni {-nonewline {}}} { + tailcall ${-nonewline} puts $msg + } + tailcall $chan puts {*}${-nonewline} $msg + } + + # read is complicated by -nonewline + # + # read chan ?maxchars? + # read -nonewline chan + proc read {{-nonewline {}} chan} { + if {${-nonewline} ni {-nonewline {}}} { + tailcall ${-nonewline} read {*}${chan} + } + tailcall $chan read {*}${-nonewline} + } + + proc fconfigure {f args} { + foreach {n v} $args { + switch -glob -- $n { + -bl* { + $f ndelay $v + } + -bu* { + $f buffering $v + } + -tr* { + # Just ignore -translation + } + default { + return -code error "fconfigure: unknown option $n" + } + } + } + } +} + +# case var ?in? pattern action ?pattern action ...? +proc case {var args} { + # Skip dummy parameter + if {[lindex $args 0] eq "in"} { + set args [lrange $args 1 end] + } + + # Check for single arg form + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + # Check for odd number of args + if {[llength $args] % 2 != 0} { + return -code error "extra case pattern with no body" + } + + # Internal function to match a value agains a list of patterns + local proc case.checker {value pattern} { + string match $pattern $value + } + + foreach {value action} $args { + if {$value eq "default"} { + set do_action $action + continue + } elseif {[lsearch -bool -command case.checker $value $var]} { + set do_action $action + break + } + } + + if {[info exists do_action]} { + set rc [catch [list uplevel 1 $do_action] result opts] + if {$rc} { + incr opts(-level) + } + return {*}$opts $result + } +} + +# fileevent isn't needed in Jim, but provide it for compatibility +proc fileevent {args} { + tailcall {*}$args +} + +# Second, option argument is a glob pattern +# Third, optional argument is a "putter" function +# +proc parray {arrayname {pattern *} {puts puts}} { + upvar $arrayname a + + set max 0 + foreach name [array names a $pattern]] { + if {[string length $name] > $max} { + set max [string length $name] + } + } + incr max [string length $arrayname] + incr max 2 + foreach name [lsort [array names a $pattern]] { + $puts [format "%-${max}s = %s" $arrayname\($name\) $a($name)] + } +} + +# Implements 'file copy' - single file mode only +proc {file copy} {{force {}} source target} { + try { + if {$force ni {{} -force}} { + error "bad option \"$force\": should be -force" + } + + set in [open $source] + + if {$force eq "" && [file exists $target]} { + $in close + error "error copying \"$source\" to \"$target\": file already exists" + } + set out [open $target w] + $in copyto $out + $out close + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg + } finally { + catch {$in close} + } +} + +# 'open "|..." ?mode?" will invoke this wrapper around exec/pipe +# Note that we return a lambda which also provides the 'pid' command +proc popen {cmd {mode r}} { + lassign [socket pipe] r w + try { + if {[string match "w*" $mode]} { + lappend cmd <@$r & + set pids [exec {*}$cmd] + $r close + set f $w + } else { + lappend cmd >@$w & + set pids [exec {*}$cmd] + $w close + set f $r + } + lambda {cmd args} {f pids} { + if {$cmd eq "pid"} { + return $pids + } + if {$cmd eq "close"} { + $f close + # And wait for the child processes to complete + foreach p $pids { os.wait $p } + return + } + tailcall $f $cmd {*}$args + } + } on error {error opts} { + $r close + $w close + error $error + } +} + +# A wrapper around 'pid' which can return the pids for 'popen' +local proc pid {{chan {}}} { + if {$chan eq ""} { + tailcall upcall pid + } + if {[catch {$chan tell}]} { + return -code error "can not find channel named \"$chan\"" + } + if {[catch {$chan pid} pids]} { + return "" + } + return $pids +} + +# try/on/finally conceptually similar to Tcl 8.6 +# +# Usage: try ?catchopts? script ?onclause ...? ?finallyclause? +# +# Where: +# onclause is: on codes {?resultvar? ?optsvar?} script +# +# codes is: a list of return codes (ok, error, etc. or integers), or * for any +# +# finallyclause is: finally script +# +# +# Where onclause is: on codes {?resultvar? ?optsvar?} +proc try {args} { + set catchopts {} + while {[string match -* [lindex $args 0]]} { + set args [lassign $args opt] + if {$opt eq "--"} { + break + } + lappend catchopts $opt + } + if {[llength $args] == 0} { + return -code error {wrong # args: should be "try ?options? script ?argument ...?"} + } + set args [lassign $args script] + set code [catch -eval {*}$catchopts [list uplevel 1 $script] msg opts] + + set handled 0 + + foreach {on codes vars script} $args { + switch -- $on \ + on { + if {!$handled && ($codes eq "*" || [info returncode $code] in $codes)} { + lassign $vars msgvar optsvar + if {$msgvar ne ""} { + upvar $msgvar hmsg + set hmsg $msg + } + if {$optsvar ne ""} { + upvar $optsvar hopts + set hopts $opts + } + # Override any body result + set code [catch [list uplevel 1 $script] msg opts] + incr handled + } + } \ + finally { + set finalcode [catch [list uplevel 1 $codes] finalmsg finalopts] + if {$finalcode} { + # Override any body or handler result + set code $finalcode + set msg $finalmsg + set opts $finalopts + } + break + } \ + default { + return -code error "try: expected 'on' or 'finally', got '$on'" + } + } + + if {$code} { + incr opts(-level) + return {*}$opts $msg + } + return $msg +} + +# Generates an exception with the given code (ok, error, etc. or an integer) +# and the given message +proc throw {code {msg ""}} { + return -code $code $msg +} + +# Helper for "file delete -force" +proc {file delete force} {path} { + foreach e [readdir $path] { + file delete -force $path/$e + } + file delete $path +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/tree.tcl b/android/external/usb_modeswitch/usb_modeswitch/jim/tree.tcl new file mode 100755 index 0000000..01fc167 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/tree.tcl @@ -0,0 +1,219 @@ +# Conceptually compatible with tcllib ::struct::tree +# but uses an object based interface. +# To mimic tcllib, do: +# rename [tree] mytree + +package require oo + +# set pt [tree] +# +# Create a tree +# This automatically creates a node named "root" +# +# $pt destroy +# +# Destroy the tree and all it's nodes +# +# $pt set <nodename> <key> <value> +# +# Set the value for the given key +# +# $pt lappend <nodename> <key> <value> ... +# +# Append to the (list) value(s) for the given key, or set if not yet set +# +# $pt keyexists <nodename> <key> +# +# Returns 1 if the given key exists +# +# $pt get <nodename> <key> +# +# Returns the value associated with the given key +# +# $pt getall <nodename> +# +# Returns the entire attribute dictionary associated with the given key +# +# $pt depth <nodename> +# +# Returns the depth of the given node. The depth of "root" is 0. +# +# $pt parent <nodename> +# +# Returns the name of the parent node, or "" for the root node. +# +# $pt numchildren <nodename> +# +# Returns the number of child nodes. +# +# $pt children <nodename> +# +# Returns a list of the child nodes. +# +# $pt next <nodename> +# +# Returns the next sibling node, or "" if none. +# +# $pt insert <nodename> ?index? +# +# Add a new child node to the given node. +# THe default index is "end" +# Returns the name of the newly added node +# +# $pt walk <nodename> dfs|bfs {actionvar nodevar} <code> +# +# Walks the tree starting from the given node, either breadth first (bfs) +# depth first (dfs). +# The value "enter" or "exit" is stored in variable $actionvar +# The name of each node is stored in $nodevar. +# The script $code is evaluated twice for each node, on entry and exit. +# +# $pt dump +# +# Dumps the tree contents to stdout + +#------------------------------------------ +# Internal implementation. +# The tree class has 4 instance variables. +# - tree is a dictionary. key=node, value=node value dictionary +# - parent is a dictionary. key=node, value=parent of this node +# - children is a dictionary. key=node, value=list of child nodes for this node +# - nodeid is an integer which increments to give each node a unique id + +# Construct a tree with a single root node with no parent and no children +class tree { + tree {root {}} + parents {root {}} + children {root {}} + nodeid 0 +} + +# Simply walk up the tree to get the depth +tree method depth {node} { + set depth 0 + while {$node ne "root"} { + incr depth + set node [dict get $parents $node] + } + return $depth +} + +tree method parent {node} { + dict get $parents $node +} + +tree method children {node} { + dict get $children $node +} + +tree method numchildren {node} { + llength [dict get $children $node] +} + +tree method next {node} { + # My siblings are my parents children + set siblings [dict get $children [dict get $parents $node]] + # Find me + set i [lsearch $siblings $node] + incr i + lindex $siblings $i +} + +tree method set {node key value} { + dict set tree $node $key $value + return $value +} + +tree method get {node key} { + dict get $tree $node $key +} + +tree method keyexists {node key} { + dict exists $tree $node $key +} + +tree method getall {node} { + dict get $tree $node +} + +tree method insert {node {index end}} { + + # Make a new node and add it to the tree + set childname node[incr nodeid] + dict set tree $childname {} + + # The new node has no children + dict set children $childname {} + + # Set the parent + dict set parents $childname $node + + # And add it as a child + set nodes [dict get $children $node] + dict set children $node [linsert $nodes $index $childname] + + return $childname +} + +tree method lappend {node key args} { + if {[dict exists $tree $node $key]} { + set result [dict get $tree $node $key] + } + lappend result {*}$args + dict set tree $node $key $result + return $result +} + +# $tree walk node bfs|dfs {action loopvar} <code> +# +tree method walk {node type vars code} { + # set up vars + lassign $vars actionvar namevar + + set n $node + + if {$type ne "child"} { + upvar 2 $namevar name $actionvar action + + # Enter this node + set name $node + set action enter + + uplevel 2 $code + } + + if {$type eq "dfs"} { + # Depth-first so do the children + foreach child [$self children $n] { + uplevel 2 [list $self walk $child $type $vars $code] + } + } elseif {$type ne "none"} { + # Breadth-first so do the children to one level only + foreach child [$self children $n] { + uplevel 2 [list $self walk $child none $vars $code] + } + + # Now our grandchildren + foreach child [$self children $n] { + uplevel 2 [list $self walk $child child $vars $code] + } + } + + if {$type ne "child"} { + # Exit this node + set name $node + set action exit + + uplevel 2 $code + } +} + +tree method dump {} { + $self walk root dfs {action n} { + set indent [string repeat " " [$self depth $n]] + if {$action eq "enter"} { + puts "$indent$n ([$self getall $n])" + } + } + puts "" +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.c b/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.c new file mode 100755 index 0000000..a81b3de --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.c @@ -0,0 +1,192 @@ +/** + * UTF-8 utility functions + * + * (c) 2010 Steve Bennett <steveb@workware.net.au> + * + * See LICENCE for licence details. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include "utf8.h" + +/* This one is always implemented */ +int utf8_fromunicode(char *p, unsigned short uc) +{ + if (uc <= 0x7f) { + *p = uc; + return 1; + } + else if (uc <= 0x7ff) { + *p++ = 0xc0 | ((uc & 0x7c0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 2; + } + else { + *p++ = 0xe0 | ((uc & 0xf000) >> 12); + *p++ = 0x80 | ((uc & 0xfc0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 3; + } +} + +#if defined(JIM_UTF8) && !defined(JIM_BOOTSTRAP) +int utf8_charlen(int c) +{ + if ((c & 0x80) == 0) { + return 1; + } + if ((c & 0xe0) == 0xc0) { + return 2; + } + if ((c & 0xf0) == 0xe0) { + return 3; + } + if ((c & 0xf8) == 0xf0) { + return 4; + } + /* Invalid sequence */ + return -1; +} + +int utf8_strlen(const char *str, int bytelen) +{ + int charlen = 0; + if (bytelen < 0) { + bytelen = strlen(str); + } + while (bytelen) { + int c; + int l = utf8_tounicode(str, &c); + charlen++; + str += l; + bytelen -= l; + } + return charlen; +} + +int utf8_index(const char *str, int index) +{ + const char *s = str; + while (index--) { + int c; + s += utf8_tounicode(s, &c); + } + return s - str; +} + +int utf8_charequal(const char *s1, const char *s2) +{ + int c1, c2; + + utf8_tounicode(s1, &c1); + utf8_tounicode(s2, &c2); + + return c1 == c2; +} + +int utf8_prev_len(const char *str, int len) +{ + int n = 1; + + assert(len > 0); + + /* Look up to len chars backward for a start-of-char byte */ + while (--len) { + if ((str[-n] & 0x80) == 0) { + /* Start of a 1-byte char */ + break; + } + if ((str[-n] & 0xc0) == 0xc0) { + /* Start of a multi-byte char */ + break; + } + n++; + } + return n; +} + +int utf8_tounicode(const char *str, int *uc) +{ + unsigned const char *s = (unsigned const char *)str; + + if (s[0] < 0xc0) { + *uc = s[0]; + return 1; + } + if (s[0] < 0xe0) { + if ((s[1] & 0xc0) == 0x80) { + *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80); + return 2; + } + } + else if (s[0] < 0xf0) { + if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) { + *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80); + return 3; + } + } + + /* Invalid sequence, so just return the byte */ + *uc = *s; + return 1; +} + +struct casemap { + unsigned short code; /* code point */ + signed char lowerdelta; /* add for lowercase, or if -128 use the ext table */ + signed char upperdelta; /* add for uppercase, or offset into the ext table */ +}; + +/* Extended table for codepoints where |delta| > 127 */ +struct caseextmap { + unsigned short lower; + unsigned short upper; +}; + +/* Generated mapping tables */ +#include "_unicode_mapping.c" + +#define NUMCASEMAP sizeof(unicode_case_mapping) / sizeof(*unicode_case_mapping) + +static int cmp_casemap(const void *key, const void *cm) +{ + return *(int *)key - (int)((const struct casemap *)cm)->code; +} + +static int utf8_map_case(int uc, int upper) +{ + const struct casemap *cm = bsearch(&uc, unicode_case_mapping, NUMCASEMAP, sizeof(*unicode_case_mapping), cmp_casemap); + + if (cm) { + if (cm->lowerdelta == -128) { + uc = upper ? unicode_extmap[cm->upperdelta].upper : unicode_extmap[cm->upperdelta].lower; + } + else { + uc += upper ? cm->upperdelta : cm->lowerdelta; + } + } + return uc; +} + +int utf8_upper(int uc) +{ + if (isascii(uc)) { + return toupper(uc); + } + return utf8_map_case(uc, 1); +} + +int utf8_lower(int uc) +{ + if (isascii(uc)) { + return tolower(uc); + } + + return utf8_map_case(uc, 0); +} + +#endif /* JIM_BOOTSTRAP */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.h b/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.h new file mode 100755 index 0000000..9ada93f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/jim/utf8.h @@ -0,0 +1,110 @@ +#ifndef UTF8_UTIL_H +#define UTF8_UTIL_H +/** + * UTF-8 utility functions + * + * (c) 2010 Steve Bennett <steveb@workware.net.au> + * + * See LICENCE for licence details. + */ +#include <jim-config.h> + +/** + * Converts the given unicode codepoint (0 - 0xffff) to utf-8 + * and stores the result at 'p'. + * + * Returns the number of utf-8 characters (1-3). + */ +int utf8_fromunicode(char *p, unsigned short uc); + +#ifndef JIM_UTF8 +#include <ctype.h> + +/* No utf-8 support. 1 byte = 1 char */ +#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) +#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) +#define utf8_upper(C) toupper(C) +#define utf8_lower(C) tolower(C) +#define utf8_index(C, I) (I) +#define utf8_charlen(C) 1 +#define utf8_prev_len(S, L) 1 + +#else +#if !defined(JIM_BOOTSTRAP) +/** + * Returns the length of the utf-8 sequence starting with 'c'. + * + * Returns 1-4, or -1 if this is not a valid start byte. + * + * Note that charlen=4 is not supported by the rest of the API. + */ +int utf8_charlen(int c); + +/** + * Returns the number of characters in the utf-8 + * string of the given byte length. + * + * Any bytes which are not part of an valid utf-8 + * sequence are treated as individual characters. + * + * The string *must* be null terminated. + * + * Does not support unicode code points > \uffff + */ +int utf8_strlen(const char *str, int bytelen); + +/** + * Returns the byte index of the given character in the utf-8 string. + * + * The string *must* be null terminated. + * + * This will return the byte length of a utf-8 string + * if given the char length. + */ +int utf8_index(const char *str, int charindex); + +/** + * Returns the unicode codepoint corresponding to the + * utf-8 sequence 'str'. + * + * Stores the result in *uc and returns the number of bytes + * consumed. + * + * If 'str' is null terminated, then an invalid utf-8 sequence + * at the end of the string will be returned as individual bytes. + * + * If it is not null terminated, the length *must* be checked first. + * + * Does not support unicode code points > \uffff + */ +int utf8_tounicode(const char *str, int *uc); + +/** + * Returns the number of bytes before 'str' that the previous + * utf-8 character sequence starts (which may be the middle of a sequence). + * + * Looks back at most 'len' bytes backwards, which must be > 0. + * If no start char is found, returns -len + */ +int utf8_prev_len(const char *str, int len); + +/** + * Returns the upper-case variant of the given unicode codepoint. + * + * Does not support unicode code points > \uffff + */ +int utf8_upper(int uc); + +/** + * Returns the lower-case variant of the given unicode codepoint. + * + * NOTE: Use utf8_upper() in preference for case-insensitive matching. + * + * Does not support unicode code points > \uffff + */ +int utf8_lower(int uc); +#endif /* JIM_BOOTSTRAP */ + +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/make_string.tcl b/android/external/usb_modeswitch/usb_modeswitch/make_string.tcl new file mode 100755 index 0000000..5a1b5ff --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/make_string.tcl @@ -0,0 +1,31 @@ +#!/usr/bin/env tclsh + +# (c) Josua Dietze 2012 +# +# Usage: make_string.tcl source.tcl >jim-source.c + +# Converts a Tcl source file into C source suitable +# for using as an embedded script. + +set source [lindex $argv 0] + +if {![string match *.tcl $source]} { + error "Source $source is not a .tcl file" +} + +# Read the Tcl source and convert to C macro +set sourcelines {} +set f [open $source] +while {[gets $f buf] >= 0} { + # Remove comment lines + regsub {^[ \t]*#.*$} $buf "" buf + # Remove leading whitespaces + set buf [string trimleft $buf] + # Escape quotes and backlashes + set buf [string map [list \\ \\\\ \" \\"] $buf] + if [string length $buf] { + lappend sourcelines "$buf\\n" + } +} +close $f +puts "#define RAW \"[join $sourcelines ""]\"" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf b/android/external/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf new file mode 100755 index 0000000..570ca65 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf @@ -0,0 +1,5 @@ +start on usb-modeswitch-upstart +task +script + exec /usr/sbin/usb_modeswitch_dispatcher --switch-upstart $UMS_PARAM +end script diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Android.mk b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Android.mk new file mode 100755 index 0000000..f9fb9cf --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Android.mk @@ -0,0 +1,47 @@ +LOCAL_PATH:= $(call my-dir) + +common_src_files := \ + NetlinkManager.cpp \ + NetlinkHandler.cpp \ + MiscManager.cpp \ + Misc.cpp \ + G3Dev.cpp + +common_shared_libraries := \ + libsysutils \ + libbinder \ + libcutils \ + liblog \ + libselinux \ + libutils \ + libbase \ + libhwbinder + +common_cflags := -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter + +#common_local_tidy_flags := -warnings-as-errors=clang-analyzer-security*,cert-* +common_local_tidy_checks := -*,clang-analyzer-security*,cert-*,-cert-err34-c,-cert-err58-cpp +common_local_tidy_checks += ,-cert-env33-c + +include $(CLEAR_VARS) + +LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk +LOCAL_MODULE := usb_dongle +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CLANG := true +LOCAL_TIDY := true +LOCAL_TIDY_FLAGS := $(common_local_tidy_flags) +LOCAL_TIDY_CHECKS := $(common_local_tidy_checks) +LOCAL_SRC_FILES := \ + main.cpp \ + $(common_src_files) + +LOCAL_INIT_RC := usb_dongle.rc + +LOCAL_CFLAGS := $(common_cflags) +#LOCAL_CFLAGS += -Werror=format +LOCAL_CFLAGS += -DUSE_USB_MODE_SWITCH + +LOCAL_SHARED_LIBRARIES := $(common_shared_libraries) + +include $(BUILD_EXECUTABLE) diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.cpp new file mode 100755 index 0000000..55d928d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <sys/wait.h> +#include <sys/types.h> + + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> +#include <sysutils/NetlinkEvent.h> + +#include "G3Dev.h" +#include "MiscManager.h" +#include <unistd.h> + +#if PLATFORM_SDK_VERSION >= 16 +#define LOGV(fmt,args...) ALOGV(fmt,##args) +#define LOGD(fmt,args...) ALOGD(fmt,##args) +#define LOGI(fmt,args...) ALOGI(fmt,##args) +#define LOGW(fmt,args...) ALOGW(fmt,##args) +#define LOGE(fmt,args...) ALOGE(fmt,##args) +#endif + +static char modeswitch_cmd[256] = ""; + + +G3Dev::G3Dev(MiscManager *mm):Misc(mm) +{ + +} + +G3Dev::~G3Dev() { +} + +int G3Dev::handleUsbEvent(NetlinkEvent *evt) { + const char *devtype = evt->findParam("DEVTYPE"); + if( devtype!=NULL &&strcmp(devtype, "usb_device") ) + return 0; + pid_t status ; + + NetlinkEvent::Action action = evt->getAction(); + if( action == NetlinkEvent::Action::kAdd) + { + const char *product = evt->findParam("PRODUCT"); + if(product!=NULL && product[0] != 0 && devtype[0] != 0 ) + { + // ��ȡVID/PID + int vid = 0; + int pid = 0; + char * next = (char*)product; + vid = strtol(product, &next, 16); + + //char pre[]="sVe.GT"; + ++next; + pid = strtol(next, NULL, 16); + + SLOGD("== current usb device: %04X/%04X ===", vid, pid); + + char configure_file[2048]; + + + sprintf(configure_file, "/vendor/etc/usb_modeswitch.d/%04x_%04x", vid, pid); + if( access(configure_file, 0) == 0 ) + { + sprintf(modeswitch_cmd, "/vendor/bin/usb_modeswitch -W -v %04x -p %04x -c %s &", vid, pid,configure_file); + SLOGD("=== USB Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + } + } + } + + return 0; +} +int G3Dev::handleScsiEvent(NetlinkEvent *evt) { +/* + ��һ��������usb_device ���event��ִ�е�usb_modeswitchû�гɹ�����Ϊ���� + �ֶΣ���SCSI���event���ٴ�ִ��usb_modeswitch + */ + if(evt->getAction()==NetlinkEvent::Action::kAdd && modeswitch_cmd[0] != 0) + { + SLOGD("=== SCSI Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + modeswitch_cmd[0] = 0; + } + + return 0; +} +int G3Dev::handleUsb(){ + + + char configure_file[2048]; + int pid,vid; + this->get_tty_id(&vid,& pid); + + sprintf(configure_file, "/vendor/etc/usb_modeswitch.d/%04x_%04x", vid,pid); + SLOGD("=== config_file is: %04x_%04x", vid ,pid); + if( access(configure_file, 0) == 0 ) + { + sprintf(modeswitch_cmd, "/vendor/bin/usb_modeswitch -W -v %04x -p %04x -c %s &", vid, pid,configure_file); + SLOGD("=== USB Switch: %s", modeswitch_cmd); + system(modeswitch_cmd); + + } + return 0; + } +int G3Dev:: get_tty_id(int *vid, int* pid) +{ + + char linkto[1024]=""; + //SLOGD("began find device path"); + // SLOGD("device path: %s", tty_path);//// + + // LOGD("USB device path: %s", plink); + char pidpath[PATH_MAX]="/sys/bus/usb/devices/1-1"; + + FILE* fp = NULL; + char buf[5] = {0}; + strlcat(pidpath, "/idVendor",PATH_MAX); + SLOGD("Vendor path: %s", pidpath); + fp = fopen(pidpath, "r"); + if(fp == NULL) + return -2; + if(fread(buf, 1, 4, fp) != 4) + { + fclose(fp); + return -2; + } + fclose(fp); + *vid = atox(buf, 16); + char vidpath[PATH_MAX]="/sys/bus/usb/devices/1-1"; + //sys/bus/usb/devices/1-1 + strlcat(vidpath, "/idProduct",PATH_MAX); + // LOGD("Product path: %s", plink); + fp = fopen(vidpath, "r"); + if(fp == NULL) + return -3; + if(fread(buf, 1, 4, fp) != 4) + { + fclose(fp); + return -3; + } + fclose(fp); + *pid =atox(buf, 16); + + return 0; +} +#define EATCHAR(x, c) for (; *(x) == (c); (x)++) ; +/* -1:error. */ +int G3Dev:: atox( const char * line, int f_base ) +{ + int base = 10; + char max = '9'; + int v = 0; + + EATCHAR(line, ' '); + if(*line == 0) return 0; + + if( line[1] == 'x' || line[1] == 'X' ){ + base = 16; + max = 'f'; /* F*/ + line += 2; + } + else if(f_base==16) + { + base = 16; + max = 'f'; /* F*/ + } + + if( base == 10 ) { + while( *line >= '0' && *line <= max ) { + v *= base ; + v += *line-'0'; + line++; + } + } else { + while( *line >= '0' && *line <= max ) { + v *= base ; + if( *line >= 'a' ) + v += *line-'a'+10; + else if ( *line >= 'A' ) + v += *line-'A'+10; + else + v += *line-'0'; + line++; + } + } + return v; +} + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.h b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.h new file mode 100755 index 0000000..2010dcb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/G3Dev.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _G3DEV_H +#define _G3DEV_H + +#include <utils/List.h> + +#include "Misc.h" +class NetlinkEvent; + +class G3Dev : public Misc { +public: + G3Dev(MiscManager *mm); + virtual ~G3Dev(); + NetlinkEvent *env; + int handleUsbEvent(NetlinkEvent *evt); + int handleScsiEvent(NetlinkEvent *evt); + int handleUsb(); + int get_tty_id(int *vid, int* pid); + int atox( const char * line, int f_base ); +}; + +#endif + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.cpp new file mode 100755 index 0000000..519201e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> + +#include <cutils/properties.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include "Misc.h" + +Misc::Misc(MiscManager *mm) +{ + mMm = mm; + mDebug = false; +} + +Misc::~Misc() +{ +} + +void Misc::setDebug(bool enable) { + mDebug = enable; +} +/* + �ú�����������ʵ�� + */ +int Misc::handleUsbEvent(NetlinkEvent *evt) { + errno = ENOSYS; + return -1; +} + +/* + �ú�����������ʵ�� + */ +int Misc::handleScsiEvent(NetlinkEvent *evt) { + errno = ENOSYS; + return -1; +} + +int Misc::handleUsb() +{ errno = ENOSYS; + return -1;} + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.h b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.h new file mode 100755 index 0000000..e3d4f93 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/Misc.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MISC_H +#define _MISC_H + +#include <utils/List.h> + +class NetlinkEvent; +class MiscManager; + +class Misc { +protected: + MiscManager *mMm; + bool mDebug; + +public: + Misc(MiscManager *mm); + virtual ~Misc(); + + virtual int handleUsbEvent(NetlinkEvent *evt); + virtual int handleScsiEvent(NetlinkEvent *evt); + virtual int handleUsb(); + void setDebug(bool enable); +}; + +typedef android::List<Misc *> MiscCollection; + +#endif + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.cpp new file mode 100755 index 0000000..06173e0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include <sysutils/NetlinkEvent.h> + +#include "MiscManager.h" + + +MiscManager *MiscManager::sInstance = NULL; + +MiscManager *MiscManager::Instance() { + if (!sInstance) + sInstance = new MiscManager(); + return sInstance; +} + +MiscManager::MiscManager() { + mDebug = false; + mMiscs = new MiscCollection(); + mBroadcaster = NULL; +} + +MiscManager::~MiscManager() { + delete mMiscs; +} + +void MiscManager::setDebug(bool enable) { + mDebug = enable; + MiscCollection::iterator it; + for (it = mMiscs->begin(); it != mMiscs->end(); ++it) { + (*it)->setDebug(enable); + } +} + +int MiscManager::start() { + return 0; +} + +int MiscManager::stop() { + return 0; +} + +int MiscManager::addMisc(Misc *m) { + mMiscs->push_back(m); + return 0; +} + +void MiscManager::handleEvent(NetlinkEvent *evt) { + const char *subsys = evt->getSubsystem(); + MiscCollection::iterator it; + bool hit = false; + + SLOGD("%s, %d", subsys, evt->getAction()); + + + for (it = mMiscs->begin(); it != mMiscs->end(); ++it) { + if (!strcmp(subsys, "usb")) { + (*it)->handleUsbEvent(evt); + } else if (!strcmp(subsys, "scsi_device")) { + (*it)->handleScsiEvent(evt); + } + } +} + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.h b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.h new file mode 100755 index 0000000..a7cee2b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/MiscManager.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MISCMANAGER_H +#define _MISCMANAGER_H + +#include <pthread.h> + +#include <utils/List.h> +#include <sysutils/SocketListener.h> +#include "Misc.h" + +class MiscManager { +private: + static MiscManager *sInstance; + +private: + SocketListener *mBroadcaster; + MiscCollection *mMiscs; + bool mDebug; + +public: + virtual ~MiscManager(); + + int start(); + int stop(); + + void handleEvent(NetlinkEvent *evt); + + int addMisc(Misc *v); + + void setDebug(bool enable); + + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } + SocketListener *getBroadcaster() { return mBroadcaster; } + + static MiscManager *Instance(); + +private: + MiscManager(); + Misc *lookupMisc(const char *label); +}; +#endif + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.cpp new file mode 100755 index 0000000..32b5180 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#define LOG_TAG "USB_DONGLE" + +#include <cutils/log.h> + +#include <sysutils/NetlinkEvent.h> +#include "NetlinkHandler.h" +#include "MiscManager.h" +NetlinkHandler::NetlinkHandler(int listenerSocket) : + NetlinkListener(listenerSocket) { +} + +NetlinkHandler::~NetlinkHandler() { +} + +int NetlinkHandler::start() { + return this->startListener(); +} + +int NetlinkHandler::stop() { + return this->stopListener(); +} + +void NetlinkHandler::onEvent(NetlinkEvent *evt) { + const char *subsys = evt->getSubsystem(); + + if (!subsys) { + SLOGW("No subsystem found in netlink event"); + return; + } + +#ifdef USE_USB_MODE_SWITCH + if (!strcmp(subsys, "usb") || !strcmp(subsys, "scsi_device")) { + SLOGW("subsystem found in netlink event"); + MiscManager *mm = MiscManager::Instance(); + mm->handleEvent(evt); +#endif + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.h b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.h new file mode 100755 index 0000000..56eb23c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkHandler.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NETLINKHANDLER_H +#define _NETLINKHANDLER_H + +#include <sysutils/NetlinkListener.h> + +class NetlinkHandler: public NetlinkListener { + +public: + explicit NetlinkHandler(int listenerSocket); + virtual ~NetlinkHandler(); + + int start(void); + int stop(void); + +protected: + virtual void onEvent(NetlinkEvent *evt); +}; +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.cpp new file mode 100755 index 0000000..63e7475 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <sys/socket.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/un.h> + +#include <linux/netlink.h> + +#define LOG_TAG "USB_DONGLE" + +#include <android-base/logging.h> + +#include "NetlinkManager.h" +#include "NetlinkHandler.h" + +NetlinkManager *NetlinkManager::sInstance = NULL; + +NetlinkManager *NetlinkManager::Instance() { + if (!sInstance) + sInstance = new NetlinkManager(); + return sInstance; +} + +NetlinkManager::NetlinkManager() { + mBroadcaster = NULL; +} + +NetlinkManager::~NetlinkManager() { +} + +int NetlinkManager::start() { + struct sockaddr_nl nladdr; + int sz = 64 * 1024; + int on = 1; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = getpid(); + nladdr.nl_groups = 0xffffffff; + + if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, + NETLINK_KOBJECT_UEVENT)) < 0) { + PLOG(ERROR) << "Unable to create uevent socket"; + return -1; + } + + // When running in a net/user namespace, SO_RCVBUFFORCE will fail because + // it will check for the CAP_NET_ADMIN capability in the root namespace. + // Try using SO_RCVBUF if that fails. + if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) && + (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) { + PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option"; + goto out; + } + + if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { + PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option"; + goto out; + } + + if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { + PLOG(ERROR) << "Unable to bind uevent socket"; + goto out; + } + + mHandler = new NetlinkHandler(mSock); + if (mHandler->start()) { + PLOG(ERROR) << "Unable to start NetlinkHandler"; + goto out; + } + + return 0; + +out: + close(mSock); + return -1; +} + +int NetlinkManager::stop() { + int status = 0; + + if (mHandler->stop()) { + PLOG(ERROR) << "Unable to stop NetlinkHandler"; + status = -1; + } + delete mHandler; + mHandler = NULL; + + close(mSock); + mSock = -1; + + return status; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.h b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.h new file mode 100755 index 0000000..9c7ba11 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/NetlinkManager.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _NETLINKMANAGER_H +#define _NETLINKMANAGER_H + +#include <sysutils/SocketListener.h> +#include <sysutils/NetlinkListener.h> + +class NetlinkHandler; + +class NetlinkManager { +private: + static NetlinkManager *sInstance; + +private: + SocketListener *mBroadcaster; + NetlinkHandler *mHandler; + int mSock; + +public: + virtual ~NetlinkManager(); + + int start(); + int stop(); + + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } + SocketListener *getBroadcaster() { return mBroadcaster; } + + static NetlinkManager *Instance(); + +private: + NetlinkManager(); +}; +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/main.cpp b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/main.cpp new file mode 100755 index 0000000..1e29146 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/main.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NetlinkManager.h" + +#include <android-base/logging.h> +#include <android-base/stringprintf.h> +#include <cutils/klog.h> +#include <cutils/properties.h> +#include <cutils/sockets.h> + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <getopt.h> +#include <fcntl.h> +#include <dirent.h> + +#ifdef USE_USB_MODE_SWITCH +#include "G3Dev.h" +#include "MiscManager.h" +#endif + +#define LOG_TAG "USB_DONGLE" + +static void coldboot(const char *path); + +struct fstab *fstab; + +struct selabel_handle *sehandle; + +using android::base::StringPrintf; + +int main(int argc, char** argv) { + setenv("ANDROID_LOG_TAGS", "*:v", 1); + android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM)); + + LOG(INFO) << "USB_MODE_SWITCH"; + + NetlinkManager *nm; + + + klog_set_level(6); + + if (!(nm = NetlinkManager::Instance())) { + LOG(ERROR) << "Unable to create NetlinkManager"; + exit(1); + } + + if (nm->start()) { + PLOG(ERROR) << "Unable to start NetlinkManager"; + exit(1); + } + +#ifdef USE_USB_MODE_SWITCH + MiscManager *mm; + if (!(mm = MiscManager::Instance())) { + PLOG(ERROR) << "Unable to create MiscManager"; + exit(1); + }; + //mm->setBroadcaster((SocketListener *) cl); + if (mm->start()) { + LOG(ERROR) << "Unable to start MiscManager"; + exit(1); + } + G3Dev* g3 = new G3Dev(mm); + g3->handleUsb(); + mm->addMisc(g3); +#endif + // Do coldboot here so it won't block booting, + // also the cold boot is needed in case we have flash drive + coldboot("/sys/block"); + // Eventually we'll become the monitoring thread + while(1) { + pause(); + } + + LOG(ERROR) << "USB_MODE_SWITCH exiting"; + exit(0); +} + +static void do_coldboot(DIR *d, int lvl) { + struct dirent *de; + int dfd, fd; + + dfd = dirfd(d); + + fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC); + if(fd >= 0) { + write(fd, "add\n", 4); + close(fd); + } + + while((de = readdir(d))) { + DIR *d2; + + if (de->d_name[0] == '.') + continue; + + if (de->d_type != DT_DIR && lvl > 0) + continue; + + fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY | O_CLOEXEC); + if(fd < 0) + continue; + + d2 = fdopendir(fd); + if(d2 == 0) + close(fd); + else { + do_coldboot(d2, lvl + 1); + closedir(d2); + } + } +} + +static void coldboot(const char *path) { + DIR *d = opendir(path); + if(d) { + do_coldboot(d, 0); + closedir(d); + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/usb_dongle.rc b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/usb_dongle.rc new file mode 100755 index 0000000..c20f161 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_dongle/usb_dongle.rc @@ -0,0 +1,4 @@ +service usb_dongle /vendor/bin/usb_dongle + class main + oneshot + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 new file mode 100755 index 0000000..fecac7c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 @@ -0,0 +1,172 @@ +.TH "USB_MODESWITCH" "1" +.SH "NAME" +usb_modeswitch - control the mode of 'multi-state' USB devices +.SH "SYNOPSIS" +.PP +\fBusb_modeswitch\fR [\fB\-heWQDIvpVPmM23rwKdHSOBGTNALnsRiuagft\fP] [\fB\-c \fIfilename\fP] +.SH "DESCRIPTION" +.PP +Several new USB devices have their proprietary Windows drivers onboard, +most of them WWAN and WLAN dongles. When plugged in for the first time, +they act like a flash storage and start installing the Windows driver from +there. If the driver is already installed, it makes the storage device +disappear and a new device, mainly composite with modem ports, shows up. +.PP +On Linux, in most cases the drivers are available as kernel modules, +such as "usbserial" or "option". However, the device initially binds to +"usb-storage" by default. \fBusb_modeswitch\fR can then send a provided bulk +message (most likely a mass storage command) to the device; this message +has to be determined by analyzing the actions of the Windows driver. +.PP +In some cases, USB control commands are used for switching. These cases are +handled by custom functions, and no bulk message needs to be provided. +.PP +Usually, the program is distributed with a set of configurations for many +known devices, which allows a fully automatic handling of a device upon +insertion, made possible by combining usb_modeswitch with the wrapper script +\fBusb_modeswitch_dispatcher\fR which is launched by the udev daemon. +.PP +Note that \fBusb_modeswitch\fR itself has no specific Linux dependencies. + +.SH "OPTIONS" +.PP +This program follows the usual GNU command line syntax, +with long options starting with two dashes ('--'). A summary of +options is included below. +.IP "\fB-h\fP \fB\-\-help\fP " 10 +Show summary of options. +.IP "\fB-e\fP \fB\-\-version\fP " 10 +Print version information and exit +.IP "\fB-v\fP \fB\-\-default-vendor NUM\fP " 10 +Vendor ID to look for (mandatory), usually given as hex number (example: 0x12d1). +Each USB device is identified by a number +officialy assigned to the vendor by the USB association and a number for the +respective model (product ID) chosen by the vendor +.IP "\fB-p\fP \fB\-\-default-product NUM\fP " 10 +Product ID to look for (mandatory) +.IP "\fB-V\fP \fB\-\-target-vendor NUM\fP " 10 +Target vendor ID. When given will be searched for and detected initially +for information purposes. If success checking (option \-s) is active, +providing target IDs (vendor/product) or target class is recommended +.IP "\fB-j\fP \fB\-\-find-mbim\fP " 10 +Return configuration number with MBIM interface and exit. +.IP "\fB-P\fP \fB\-\-target-product NUM\fP " 10 +Target product ID +.IP "\fB-b\fP \fB\-\-bus-num NUM\fP " 10 +.IP "\fB-g\fP \fB\-\-device-num NUM\fP " 10 +If bus and device number are provided, the handling of a specific device on +a specific USB port is guaranteed, in contrast to using only the USB ID. This +is important if there are multiple similar devices on a system +.IP "\fB-C\fP \fB\-\-target-class NUM\fP " 10 +Target Device Class according to the USB specification. Some devices keep +their original vendor/product ID after successful switching. To prevent +them from being treated again, the device class can be checked. +For unswitched devices it is always 8 (storage class), for switched +modems it is often 0xff (vendor specific). In composite modes, +the class of the first interface is watched +.IP "\fB-m\fP \fB\-\-message-endpoint NUM\fP " 10 +A specific endpoint to use for data transfers. Only for testing purposes; usually +endpoints are determined from the device attributes +.IP "\fB-M\fP \fB\-\-message-content STRING\fP " 10 +A bulk message to send as a switching command. Provided as a hexadecimal string +.IP "\fB-2, -3\fP \fB\-\-message-content2, \-\-message-content3 STRING\fP " 10 +Additional bulk messages to send as switching commands. Provided as hexadecimal strings. +When used with mass storage commands, setting \fB\-\-need-response\fR is +strongly advised to comply with specifications and to avoid likely errors +.IP "\fB-w\fP \fB\-\-release-delay NUM\fP " 10 +After issuing all bulk messages, wait for NUM milliseconds before releasing the interface. +Required for some modems on older systems (especially after an EJECT message) +.IP "\fB-n\fP \fB\-\-need-response\fP " 10 +Obsolete. CSW is always attempted to being read after mass storage transfers. No downside +.IP "\fB-r\fP \fB\-\-response-endpoint NUM\fP " 10 +Try to read the response to a storage command from there. Only for testing purposes; +usually endpoints are determined from the device attributes +.IP "\fB-K\fP \fB\-\-std-eject\fP " 10 +Apply the standard SCSI sequence of "Allow Medium Removal" and +"Eject". Implies \fB-n\fP. One 'Message' can be added with \fB-M\fP +that will be transmitted after the eject sequence. Used by many modems +.IP "\fB-d\fP \fB\-\-detach-only\fP " 10 +Just detach the current driver. This is sufficient for some early +devices to switch successfully. Otherwise this feature can +be used as a 'scalpel' for special cases, like separating the +driver from individual interfaces +.IP "\fB-H\fP \fB\-\-huawei-mode\fP " 10 +Send a special control message used by older Huawei devices +.IP "\fB-J\fP \fB\-\-huawei-new-mode\fP " 10 +Send a specific bulk message used by all newer Huawei devices +.IP "\fB-S\fP \fB\-\-sierra-mode\fP " 10 +Send a special control message used by Sierra devices +.IP "\fB-G\fP \fB\-\-gct-mode\fP " 10 +Send a special control message used by GCT chipsets +.IP "\fB-T\fP \fB\-\-kobil-mode\fP " 10 +Send a special control message used by Kobil devices +.IP "\fB-N\fP \fB\-\-sequans-mode\fP " 10 +Send a special control message used by Sequans chipset +.IP "\fB-A\fP \fB\-\-mobileaction-mode\fP " 10 +Send a special control message used by the MobileAction device +.IP "\fB-B\fP \fB\-\-qisda-mode\fP " 10 +Send a special control message used by Qisda devices +.IP "\fB-E\fP \fB\-\-quanta-mode\fP " 10 +Send a special control message used by Quanta devices +.IP "\fB-F\fP \fB\-\-pantech-mode NUM\fP " 10 +Send a special control message used by Pantech devices. +Value NUM will be used in control message as 'wValue' +.IP "\fB-Z\fP \fB\-\-blackberry-mode\fP " 10 +Send a special control message used by some newer Blackberry devices +.IP "\fB-S\fP \fB\-\-option-mode\fP " 10 +Send a special control message used by all Option devices +.IP "\fB-O\fP \fB\-\-sony-mode\fP " 10 +Apply a special sequence used by Sony Ericsson devices. Implies option \--check-success +.IP "\fB-L\fP \fB\-\-cisco-mode\fP " 10 +Send a sequence of bulk messages used by Cisco devices +.IP "\fB-R\fP \fB\-\-reset-usb\fP " 10 +Send a USB reset command to the device. Can be combined with any switching +method or stand alone. It is always done as the last step of all device +interactions. +Few devices need it to complete the switching; apart from that it may be +useful during testing +.IP "\fB-c\fP \fB\-\-config-file FILENAME\fP " 10 +Use a specific config file. If any ID or switching options are given as +command line parameters, this option is ignored. +In that case all mandatory parameters have to be provided on +the command line +.IP "\fB-f\fP \fB\-\-long-config STRING\fP " 10 +Provide device details in config file syntax as a multiline string +on the command line +.IP "\fB-t\fP \fB\-\-stdinput\fP " 10 +Read the device details in config file syntax from standard input, e.g. redirected from +a command pipe (multiline text) +.IP "\fB-Q\fP \fB\-\-quiet\fP " 10 +Don't show progress or error messages +.IP "\fB-W\fP \fB\-\-verbose\fP " 10 +Print all settings before running and show libusb debug messages +.IP "\fB-D\fP \fB\-\-sysmode\fP " 10 +Changes the behaviour of the program slightly. A success message including the +effective target device ID is put out and a syslog notice is issued. Mainly for +integration with a wrapper script +.IP "\fB-s\fP \fB\-\-check-success NUM\fP " 10 +After switching, keep checking for the result up to max. NUM seconds. If target IDs +or target class were provided, their appearance indicates certain success. Otherwise +the disconnection of the original device is rated as likely proof +.IP "\fB-I\fP \fB\-\-inquire\fP " 10 +Obsolete. Formerly obtained SCSI attributes, now ignored +.IP "\fB-i\fP \fB\-\-interface NUM\fP " 10 +Select initial USB interface (default: 0). Only for testing purposes +.IP "\fB-u\fP \fB\-\-configuration NUM\fP " 10 +Select USB configuration (applied after any other possible switching actions) +.IP "\fB-a\fP \fB\-\-altsetting NUM\fP " 10 +Select alternative USB interface setting (applied after switching). Mainly +for testing +.SH "AUTHOR" +.PP +This manual page was originally written by Didier Raboud (didier@raboud.com) for +the \fBDebian\fP system. Additions made by Josua Dietze. Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 or any +later version published by the Free Software Foundation. + +.PP +The complete text of the current GNU General Public +License can be found in http://www.gnu.org/licenses/gpl.txt + +.\" last edited 2016-01-11 for version 2.3.0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c new file mode 100755 index 0000000..ba5be82 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.c @@ -0,0 +1,2095 @@ +/* + Mode switching tool for controlling mode of 'multi-state' USB devices + Version 2.4.0, 2016/06/12 + + Copyright (C) 2007 - 2016 Josua Dietze (mail to "usb_admin" at the domain + of the home page; or write a personal message through the forum to "Josh". + NO SUPPORT VIA E-MAIL - please use the forum for that) + + Major contributions: + + Command line parsing, decent usage/config output/handling, bugfixes and advanced + options added by: + Joakim Wennergren + + TargetClass parameter implementation to support new Option devices/firmware: + Paul Hardwick (http://www.pharscape.org) + + Created with initial help from: + "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl) + + Config file parsing code borrowed from: + Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html) + + Hexstr2bin function borrowed from: + Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c") + + Other contributions: see README + + Device information contributors are named in the "device_reference.txt" file. See + homepage. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details: + + http://www.gnu.org/licenses/gpl.txt + +*/ + +/* Recommended tab size: 4 */ + +#define VERSION "2.4.0" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <ctype.h> +#include <getopt.h> +#include <syslog.h> +#include <unistd.h> + +#include "usb_modeswitch.h" + + +// Little helpers + +int usb_bulk_io(struct libusb_device_handle *handle, int ep, unsigned char *bytes, + int size, int timeout) +{ + int actual_length; + int r; +// usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); + r = libusb_bulk_transfer(handle, ep & 0xff, bytes, size, + &actual_length, timeout); + + /* if we timed out but did transfer some data, report as successful short + * read. FIXME: is this how libusb-0.1 works? */ + if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) + return actual_length; + + return r; +} + + +static int usb_interrupt_io(libusb_device_handle *handle, int ep, unsigned char *bytes, + int size, int timeout) +{ + int actual_length; + int r; +// usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); + r = libusb_interrupt_transfer(handle, ep & 0xff, bytes, size, + &actual_length, timeout); + + /* if we timed out but did transfer some data, report as successful short + * read. FIXME: is this how libusb-0.1 works? */ + if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) + return actual_length; + + return (r); +} + + +#define LINE_DIM 1024 +#define MSG_DIM 11 +#define MAXLINES 50 +#define BUF_SIZE 4096 +#define DESCR_MAX 129 + +#define SEARCH_DEFAULT 0 +#define SEARCH_TARGET 1 +#define SEARCH_BUSDEV 2 + +#define SWITCH_CONFIG_MAXTRIES 5 + +#define SHOW_PROGRESS if (show_progress) fprintf + +char *TempPP=NULL; + +static struct libusb_context *ctx = NULL; +static struct libusb_device *dev = NULL; +static struct libusb_device_handle *devh = NULL; +static struct libusb_config_descriptor *active_config = NULL; + +int DefaultVendor=0, DefaultProduct=0, TargetVendor=0, TargetProduct=-1, TargetClass=0; +int MessageEndpoint=0, ResponseEndpoint=0, ReleaseDelay=0; +int targetDeviceCount=0, searchMode; +int devnum=-1, busnum=-1; + +unsigned int ModeMap = 0; +#define DETACHONLY_MODE 0x00000001 +#define HUAWEI_MODE 0x00000002 +#define SIERRA_MODE 0x00000004 +#define SONY_MODE 0x00000008 +#define GCT_MODE 0x00000010 +#define KOBIL_MODE 0x00000020 +#define SEQUANS_MODE 0x00000040 +#define MOBILEACTION_MODE 0x00000080 +#define CISCO_MODE 0x00000100 +#define QISDA_MODE 0x00000200 +#define QUANTA_MODE 0x00000400 +#define BLACKBERRY_MODE 0x00000800 +#define PANTECH_MODE 0x00001000 +#define HUAWEINEW_MODE 0x00002000 +#define OPTION_MODE 0x00004000 + + +int PantechMode=0; +char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0; +char NoDriverLoading=0, sysmode=0, mbim=0; +char StandardEject=0; + +char MessageContent[LINE_DIM]; +char MessageContent2[LINE_DIM]; +char MessageContent3[LINE_DIM]; +char TargetProductList[LINE_DIM]; +char DefaultProductList[5]; +unsigned char ByteString[LINE_DIM/2]; +unsigned char buffer[BUF_SIZE]; +char **Messages = NULL; + +FILE *output; + + +/* Settable Interface and Configuration (for debugging mostly) (jmw) */ +int Interface = -1, Configuration = 0, AltSetting = -1; + + +static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'e'}, + {"default-vendor", required_argument, 0, 'v'}, + {"default-product", required_argument, 0, 'p'}, + {"target-vendor", required_argument, 0, 'V'}, + {"target-product", required_argument, 0, 'P'}, + {"target-class", required_argument, 0, 'C'}, + {"message-endpoint", required_argument, 0, 'm'}, + {"message-content", required_argument, 0, 'M'}, + {"message-content2", required_argument, 0, '2'}, + {"message-content3", required_argument, 0, '3'}, + {"release-delay", required_argument, 0, 'w'}, + {"response-endpoint", required_argument, 0, 'r'}, + {"bus-num", required_argument, 0, 'b'}, + {"device-num", required_argument, 0, 'g'}, + {"detach-only", no_argument, 0, 'd'}, + {"huawei-mode", no_argument, 0, 'H'}, + {"huawei-new-mode", no_argument, 0, 'J'}, + {"sierra-mode", no_argument, 0, 'S'}, + {"sony-mode", no_argument, 0, 'O'}, + {"qisda-mode", no_argument, 0, 'B'}, + {"quanta-mode", no_argument, 0, 'E'}, + {"kobil-mode", no_argument, 0, 'T'}, + {"gct-mode", no_argument, 0, 'G'}, + {"sequans-mode", no_argument, 0, 'N'}, + {"mobileaction-mode", no_argument, 0, 'A'}, + {"cisco-mode", no_argument, 0, 'L'}, + {"blackberry-mode", no_argument, 0, 'Z'}, + {"option-mode", no_argument, 0, 'U'}, + {"pantech-mode", required_argument, 0, 'F'}, + {"std-eject", no_argument, 0, 'K'}, + {"need-response", no_argument, 0, 'n'}, + {"reset-usb", no_argument, 0, 'R'}, + {"config-file", required_argument, 0, 'c'}, + {"verbose", no_argument, 0, 'W'}, + {"quiet", no_argument, 0, 'Q'}, + {"sysmode", no_argument, 0, 'D'}, + {"inquire", no_argument, 0, 'I'}, + {"stdinput", no_argument, 0, 't'}, + {"find-mbim", no_argument, 0, 'j'}, + {"long-config", required_argument, 0, 'f'}, + {"check-success", required_argument, 0, 's'}, + {"interface", required_argument, 0, 'i'}, + {"configuration", required_argument, 0, 'u'}, + {"altsetting", required_argument, 0, 'a'}, + {0, 0, 0, 0} +}; + + +void readConfigFile(const char *configFilename) +{ + ParseParamHex(configFilename, TargetVendor); + ParseParamHex(configFilename, TargetProduct); + ParseParamString(configFilename, TargetProductList); + ParseParamHex(configFilename, TargetClass); + ParseParamHex(configFilename, DefaultVendor); + ParseParamHex(configFilename, DefaultProduct); + ParseParamBoolMap(configFilename, DetachStorageOnly, ModeMap, DETACHONLY_MODE); + ParseParamBoolMap(configFilename, HuaweiMode, ModeMap, HUAWEI_MODE); + ParseParamBoolMap(configFilename, HuaweiNewMode, ModeMap, HUAWEINEW_MODE); + ParseParamBoolMap(configFilename, SierraMode, ModeMap, SIERRA_MODE); + ParseParamBoolMap(configFilename, SonyMode, ModeMap, SONY_MODE); + ParseParamBoolMap(configFilename, GCTMode, ModeMap, GCT_MODE); + ParseParamBoolMap(configFilename, KobilMode, ModeMap, KOBIL_MODE); + ParseParamBoolMap(configFilename, SequansMode, ModeMap, SEQUANS_MODE); + ParseParamBoolMap(configFilename, MobileActionMode, ModeMap, MOBILEACTION_MODE); + ParseParamBoolMap(configFilename, CiscoMode, ModeMap, CISCO_MODE); + ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE); + ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE); + ParseParamBoolMap(configFilename, OptionMode, ModeMap, OPTION_MODE); + ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE); + ParseParamInt(configFilename, PantechMode); + if (PantechMode) + ModeMap |= PANTECH_MODE; + ParseParamBool(configFilename, StandardEject); + ParseParamBool(configFilename, NoDriverLoading); + ParseParamHex(configFilename, MessageEndpoint); + ParseParamString(configFilename, MessageContent); + ParseParamString(configFilename, MessageContent2); + ParseParamString(configFilename, MessageContent3); + ParseParamInt(configFilename, ReleaseDelay); + ParseParamHex(configFilename, ResponseEndpoint); + ParseParamHex(configFilename, ResetUSB); + ParseParamInt(configFilename, CheckSuccess); + ParseParamHex(configFilename, Interface); + ParseParamHex(configFilename, Configuration); + ParseParamHex(configFilename, AltSetting); + + /* TargetProductList has priority over TargetProduct */ + if (TargetProduct != -1 && TargetProductList[0] != '\0') { + TargetProduct = -1; + SHOW_PROGRESS(output,"Warning: TargetProductList overrides TargetProduct!\n"); + } + + config_read = 1; +} + + +void printConfig() +{ + if ( DefaultVendor ) + fprintf (output,"DefaultVendor= 0x%04x\n", DefaultVendor); + if ( DefaultProduct ) + fprintf (output,"DefaultProduct= 0x%04x\n", DefaultProduct); + if ( TargetVendor ) + fprintf (output,"TargetVendor= 0x%04x\n", TargetVendor); + if ( TargetProduct > -1 ) + fprintf (output,"TargetProduct= 0x%04x\n", TargetProduct); + if ( TargetClass ) + fprintf (output,"TargetClass= 0x%02x\n", TargetClass); + if ( strlen(TargetProductList) ) + fprintf (output,"TargetProductList=\"%s\"\n", TargetProductList); + if (StandardEject) + fprintf (output,"\nStandardEject=1\n"); + if (ModeMap & DETACHONLY_MODE) + fprintf (output,"\nDetachStorageOnly=1\n"); + if (ModeMap & HUAWEI_MODE) + fprintf (output,"HuaweiMode=1\n"); + if (ModeMap & HUAWEINEW_MODE) + fprintf (output,"HuaweiNewMode=1\n"); + if (ModeMap & SIERRA_MODE) + fprintf (output,"SierraMode=1\n"); + if (ModeMap & SONY_MODE) + fprintf (output,"SonyMode=1\n"); + if (ModeMap & QISDA_MODE) + fprintf (output,"QisdaMode=1\n"); + if (ModeMap & QUANTA_MODE) + fprintf (output,"QuantaMode=1\n"); + if (ModeMap & GCT_MODE) + fprintf (output,"GCTMode=1\n"); + if (ModeMap & KOBIL_MODE) + fprintf (output,"KobilMode=1\n"); + if (ModeMap & SEQUANS_MODE) + fprintf (output,"SequansMode=1\n"); + if (ModeMap & MOBILEACTION_MODE) + fprintf (output,"MobileActionMode=1\n"); + if (ModeMap & CISCO_MODE) + fprintf (output,"CiscoMode=1\n"); + if (ModeMap & BLACKBERRY_MODE) + fprintf (output,"BlackberryMode=1\n"); + if (ModeMap & OPTION_MODE) + fprintf (output,"OptionMode=1\n"); + if (ModeMap & PANTECH_MODE) + fprintf (output,"PantechMode=1\n"); + if ( MessageEndpoint ) + fprintf (output,"MessageEndpoint=0x%02x\n", MessageEndpoint); + if ( strlen(MessageContent) ) + fprintf (output,"MessageContent=\"%s\"\n", MessageContent); + if ( strlen(MessageContent2) ) + fprintf (output,"MessageContent2=\"%s\"\n", MessageContent2); + if ( strlen(MessageContent3) ) + fprintf (output,"MessageContent3=\"%s\"\n", MessageContent3); + if ( ResponseEndpoint ) + fprintf (output,"ResponseEndpoint=0x%02x\n", ResponseEndpoint); + if ( Interface > -1 ) + fprintf (output,"Interface=0x%02x\n", Interface); + if ( Configuration > 0 ) + fprintf (output,"Configuration=0x%02x\n", Configuration); + if ( AltSetting > -1 ) + fprintf (output,"AltSetting=0x%02x\n", AltSetting); + if ( CheckSuccess ) + fprintf (output,"Success check enabled, max. wait time %d seconds\n", CheckSuccess); + if ( sysmode ) + fprintf (output,"System integration mode enabled\n"); +} + + +int readArguments(int argc, char **argv) +{ + int c, option_index = 0, count=0; + char *longConfig = NULL; + if (argc==1) + { + printHelp(); + printVersion(); + exit(1); + } + + while (1) + { + c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZUF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + count++; + switch (c) + { + case 'R': ResetUSB = 1; break; + case 'v': DefaultVendor = strtol(optarg, NULL, 16); break; + case 'p': DefaultProduct = strtol(optarg, NULL, 16); break; + case 'V': TargetVendor = strtol(optarg, NULL, 16); break; + case 'P': TargetProduct = strtol(optarg, NULL, 16); break; + case 'C': TargetClass = strtol(optarg, NULL, 16); break; + case 'm': MessageEndpoint = strtol(optarg, NULL, 16); break; + case 'M': strncpy(MessageContent, optarg, LINE_DIM); break; + case '2': strncpy(MessageContent2, optarg, LINE_DIM); break; + case '3': strncpy(MessageContent3, optarg, LINE_DIM); break; + case 'w': ReleaseDelay = strtol(optarg, NULL, 10); break; + case 'n': break; + case 'r': ResponseEndpoint = strtol(optarg, NULL, 16); break; + case 'K': StandardEject = 1; break; + case 'd': ModeMap = ModeMap + DETACHONLY_MODE; break; + case 'H': ModeMap = ModeMap + HUAWEI_MODE; break; + case 'J': ModeMap = ModeMap + HUAWEINEW_MODE; break; + case 'S': ModeMap = ModeMap + SIERRA_MODE; break; + case 'O': ModeMap = ModeMap + SONY_MODE; break;; break; + case 'B': ModeMap = ModeMap + QISDA_MODE; break; + case 'E': ModeMap = ModeMap + QUANTA_MODE; break; + case 'G': ModeMap = ModeMap + GCT_MODE; break; + case 'T': ModeMap = ModeMap + KOBIL_MODE; break; + case 'N': ModeMap = ModeMap + SEQUANS_MODE; break; + case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break; + case 'L': ModeMap = ModeMap + CISCO_MODE; break; + case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break; + case 'U': ModeMap = ModeMap + OPTION_MODE; break; + case 'F': ModeMap = ModeMap + PANTECH_MODE; + PantechMode = strtol(optarg, NULL, 10); break; + case 'c': readConfigFile(optarg); break; + case 't': readConfigFile("stdin"); break; + case 'W': verbose = 1; show_progress = 1; count--; break; + case 'Q': show_progress = 0; verbose = 0; count--; break; + case 'D': sysmode = 1; count--; break; + case 's': CheckSuccess = strtol(optarg, NULL, 10); count--; break; + case 'I': break; + case 'b': busnum = strtol(optarg, NULL, 10); break; + case 'g': devnum = strtol(optarg, NULL, 10); break; + + case 'i': Interface = strtol(optarg, NULL, 16); break; + case 'u': Configuration = strtol(optarg, NULL, 16); break; + case 'a': AltSetting = strtol(optarg, NULL, 16); break; + case 'j': mbim = 1; break; + + case 'f': + longConfig = malloc(strlen(optarg)+5); + strcpy(longConfig,"##\n"); + strcat(longConfig,optarg); + strcat(longConfig,"\n"); + readConfigFile(longConfig); + free(longConfig); + break; + + case 'e': + printVersion(); + exit(0); + break; + case 'h': + printVersion(); + printHelp(); + exit(0); + break; + + default: /* Unsupported - error message has already been printed */ + fprintf (output,"\n"); + printHelp(); + exit(1); + } + } + return count; +} + + +int main(int argc, char **argv) +{ + int ret=0, numDefaults=0, sonySuccess=0, i; + int currentConfigVal=0, defaultClass=0, interfaceClass=0; + struct libusb_device_descriptor descriptor; + enum libusb_error libusbError; + + /* Make sure we have empty strings even if not set by config */ + TargetProductList[0] = '\0'; + MessageContent[0] = '\0'; + MessageContent2[0] = '\0'; + MessageContent3[0] = '\0'; + DefaultProductList[0] = '\0'; + + /* Useful for debugging during boot */ +// output=fopen("/dev/console", "w"); + output=stdout; + + signal(SIGTERM, release_usb_device); + + /* + * Parameter parsing, USB preparation/diagnosis, plausibility checks + */ + + /* Check command arguments, use params instead of config file when given */ + switch (readArguments(argc, argv)) { + case 0: /* no argument or -W, -q or -s */ + break; + default: /* one or more arguments except -W, -q or -s */ + if (!config_read) /* if arguments contain -c, the config file was already processed */ + if (verbose) fprintf(output,"Take all parameters from the command line\n\n"); + } + + if (verbose) { + printVersion(); + printConfig(); + fprintf(output,"\n"); + } + + /* Some sanity checks. The default IDs are mandatory */ + if (!(DefaultVendor && DefaultProduct)) { + SHOW_PROGRESS(output,"No default vendor/product ID given. Abort\n\n"); + exit(1); + } + + if (strlen(MessageContent)) { + if (strlen(MessageContent) % 2 != 0) { + fprintf(stderr, "Error: MessageContent hex string has uneven length. Abort\n\n"); + exit(1); + } + if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) { + fprintf(stderr, "Error: MessageContent %s\n is not a hex string. Abort\n\n", + MessageContent); + + exit(1); + } + } + + if (devnum == -1) { + searchMode = SEARCH_DEFAULT; + } else { + SHOW_PROGRESS(output,"Use given bus/device number: %03d/%03d ...\n", busnum, devnum); + searchMode = SEARCH_BUSDEV; + } + + if (show_progress) + if (CheckSuccess && !(TargetVendor || TargetProduct > -1 || TargetProductList[0] != '\0') + && !TargetClass) + + fprintf(output,"Note: No target parameter given; success check limited\n"); + + if (TargetProduct > -1 && TargetProductList[0] == '\0') { + sprintf(TargetProductList,"%04x",TargetProduct); + TargetProduct = -1; + } + + /* libusb initialization */ + if ((libusbError = libusb_init(&ctx)) != LIBUSB_SUCCESS) { + //fprintf(stderr, "Error: Failed to initialize libusb. %s (%d)\n\n", + //libusb_error_name(libusbError), libusbError); + exit(1); + } + + if (verbose) + libusb_set_debug(ctx, 3); + + if (mbim) { + printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) ); + exit(0); + } + + /* Count existing target devices, remember for success check */ + if (searchMode != SEARCH_BUSDEV && (TargetVendor || TargetClass)) { + SHOW_PROGRESS(output,"Look for target devices ...\n"); + search_devices(&targetDeviceCount, TargetVendor, TargetProductList, TargetClass, 0, + SEARCH_TARGET); + + if (targetDeviceCount) { + SHOW_PROGRESS(output," Found devices in target mode or class (%d)\n", targetDeviceCount); + } else + SHOW_PROGRESS(output," No devices in target mode or class found\n"); + } + + /* Count default devices, get the last one found */ + SHOW_PROGRESS(output,"Look for default devices ...\n"); + + sprintf(DefaultProductList,"%04x",DefaultProduct); + dev = search_devices(&numDefaults, DefaultVendor, DefaultProductList, TargetClass, + Configuration, searchMode); + + if (numDefaults) { + SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults); + } else { + SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n"); + close_all(); + exit(0); + } + + if (dev == NULL) { + SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n"); + close_all(); + exit(0); + } else { + if (devnum == -1) { + devnum = libusb_get_device_address(dev); + busnum = libusb_get_bus_number(dev); + SHOW_PROGRESS(output,"Access device %03d on bus %03d\n", devnum, busnum); + } + libusb_open(dev, &devh); + if (devh == NULL) { + SHOW_PROGRESS(output,"Error opening the device. Abort\n\n"); + abortExit(); + } + } + + /* Get current configuration of default device, note value if Configuration + * parameter is set. Also sets active_config + */ + currentConfigVal = get_current_config_value(dev); + if (Configuration > -1) { + SHOW_PROGRESS(output,"Current configuration number is %d\n", currentConfigVal); + } else + currentConfigVal = 0; + + libusb_get_device_descriptor(dev, &descriptor); + defaultClass = descriptor.bDeviceClass; + if (Interface == -1) + Interface = active_config->interface[0].altsetting[0].bInterfaceNumber; + SHOW_PROGRESS(output,"Use interface number %d\n", Interface); + + /* Get class of default device/interface */ + interfaceClass = get_interface_class(); + + /* Check or get endpoints and alloc message list if needed*/ + if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE + || ModeMap & HUAWEINEW_MODE || ModeMap & OPTION_MODE) { + + Messages = (char**) calloc(MSG_DIM, sizeof(char*)); + for (i = 0; i < MSG_DIM; i++) { + Messages[i] = (char*) calloc(LINE_DIM, sizeof(char)); + Messages[i][0] = '\0'; + } + + if (!MessageEndpoint) + MessageEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT); + if (!ResponseEndpoint) + ResponseEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN); + if (!MessageEndpoint) { + fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n"); + abortExit(); + } + if (!ResponseEndpoint) { + fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n"); + abortExit(); + } + SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint, + ResponseEndpoint); + + } + + if (interfaceClass == -1) { + fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface); + abortExit(); + } + + if (defaultClass == 0 || defaultClass == 0xef) + defaultClass = interfaceClass; + else + if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE + && defaultClass != LIBUSB_CLASS_VENDOR_SPEC) { + + /* Unexpected default class combined with differing interface class */ + SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass); + defaultClass = 8; + } + + if (strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0) + if (defaultClass != 8) { + fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n" + " interface class is %d, expected 8. Abort\n\n", Interface, defaultClass); + abortExit(); + } + + if (show_progress) { + fprintf(output,"\nUSB description data (for identification)\n"); + deviceDescription(); + } + + /* Special modes are exclusive, so check for illegal combinations. + * More than one bit set? + */ + if ( ModeMap & (ModeMap-1) ) { + fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n"); + abortExit(); + } + + if ((strlen(MessageContent) || StandardEject) && ModeMap ) { + MessageContent[0] = '\0'; + StandardEject = 0; + fprintf(output,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n"); + } + + if (StandardEject && (strlen(MessageContent2) || strlen(MessageContent3))) { + fprintf(output,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n"); + } + + if ( !ModeMap && !strlen(MessageContent) && AltSetting == -1 && !Configuration && !StandardEject ) + SHOW_PROGRESS(output,"Warning: no switching method given. See documentation\n"); + + /* + * The switching actions + */ + + if (sysmode) { + openlog("usb_modeswitch", 0, LOG_SYSLOG); + syslog(LOG_NOTICE, "switch device %04x:%04x on %03d/%03d", DefaultVendor, DefaultProduct, + busnum, devnum); + + } + + if (ModeMap & DETACHONLY_MODE) { + SHOW_PROGRESS(output,"Detach storage driver as switching method ...\n"); + ret = detachDriver(); + if (ret == 2) + SHOW_PROGRESS(output," You may want to remove the storage driver manually\n"); + } + + if(ModeMap & HUAWEI_MODE) { + switchHuaweiMode(); + } + if(ModeMap & SIERRA_MODE) { + switchSierraMode(); + } + if(ModeMap & GCT_MODE) { + detachDriver(); + switchGCTMode(); + } + if(ModeMap & QISDA_MODE) { + switchQisdaMode(); + } + if(ModeMap & KOBIL_MODE) { + detachDriver(); + switchKobilMode(); + } + if(ModeMap & QUANTA_MODE) { + switchQuantaMode(); + } + if(ModeMap & SEQUANS_MODE) { + switchSequansMode(); + } + if(ModeMap & MOBILEACTION_MODE) { + switchActionMode(); + } + if(ModeMap & CISCO_MODE) { + detachDriver(); + switchCiscoMode(); + } + if(ModeMap & BLACKBERRY_MODE) { + detachDriver(); + switchBlackberryMode(); + } + if(ModeMap & PANTECH_MODE) { + detachDriver(); + if (PantechMode > 1) + switchPantechMode(); + else + SHOW_PROGRESS(output,"Waiting for auto-switch of Pantech modem ...\n"); + } + if(ModeMap & SONY_MODE) { + if (CheckSuccess) + SHOW_PROGRESS(output,"Note: CheckSuccess ignored; Sony mode does separate checks\n"); + CheckSuccess = 0; /* separate and implied success control */ + sonySuccess = switchSonyMode(); + } + + if (StandardEject) { + SHOW_PROGRESS(output,"Sending standard EJECT sequence\n"); + detachDriver(); + + strcpy(Messages[0],"5553424387654321000000000000061e000000000000000000000000000000"); + strcpy(Messages[1],"5553424397654321000000000000061b000000020000000000000000000000"); + strcpy(Messages[2],"5553424387654321000000000001061e000000000000000000000000000000"); + strcpy(Messages[3],"5553424397654321000000000001061b000000020000000000000000000000"); + if (MessageContent[0] != '\0') + strcpy(Messages[4], MessageContent); + + switchSendMessage(); + } else if (ModeMap & HUAWEINEW_MODE) { + SHOW_PROGRESS(output,"Using standard Huawei switching message\n"); + detachDriver(); + strcpy(Messages[0],"55534243123456780000000000000011062000000101000100000000000000"); + switchSendMessage(); + } else if (ModeMap & OPTION_MODE) { + SHOW_PROGRESS(output,"Using standard Option switching message\n"); + detachDriver(); +// strcpy(MessageContent,"55534243123456780100000080000601000000000000000000000000000000"); + strcpy(Messages[0],"55534243123456780000000000000601000000000000000000000000000000"); + switchSendMessage(); + } else if (strlen(MessageContent)) { + detachDriver(); + strcpy(Messages[0],MessageContent); + switchSendMessage(); + } + + if (Configuration > 0) { + if (currentConfigVal != Configuration) { + if (switchConfiguration()) { + currentConfigVal = get_current_config_value(dev); + if (currentConfigVal == Configuration) { + SHOW_PROGRESS(output,"The configuration was set successfully\n"); + } else { + SHOW_PROGRESS(output,"Changing the configuration has failed\n"); + } + } + } else { + SHOW_PROGRESS(output,"Target configuration %d found. Do nothing\n", currentConfigVal); + } + } + + if (AltSetting != -1) { + switchAltSetting(); + } + + /* No "removal" check if these are set */ + if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) { + libusb_close(devh); + devh = NULL; + } + + if (ResetUSB) { + resetUSB(); + devh = NULL; + } + + if (searchMode == SEARCH_BUSDEV && sysmode) { + printf("ok:busdev\n"); + close_all(); + exit(0); + } + + if (CheckSuccess) { + if (checkSuccess()) { + if (sysmode) { + if (NoDriverLoading) + printf("ok:\n"); + else + if (TargetProduct < 1) + printf("ok:no_data\n"); + else + printf("ok:%04x:%04x\n", TargetVendor, TargetProduct); + } + } else + if (sysmode) + printf("fail:\n"); + } else { + if (ModeMap & SONY_MODE) + if (sonySuccess) { + if (sysmode) { + syslog(LOG_NOTICE, "switched S.E. MD400 to modem mode"); + printf("ok:\n"); /* ACM device, no driver action */ + } + SHOW_PROGRESS(output,"-> device should be stable now. Bye!\n\n"); + } else { + if (sysmode) + printf("fail:\n"); + SHOW_PROGRESS(output,"-> switching was probably not completed. Bye!\n\n"); + } + else + SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n"); + } + close_all(); + exit(0); +} + + +/* Get descriptor strings if available (identification details) */ +void deviceDescription () +{ + char imanufact[DESCR_MAX], iproduct[DESCR_MAX], iserial[DESCR_MAX]; + int ret=0; + char* c; + memset (imanufact, ' ', DESCR_MAX); + memset (iproduct, ' ', DESCR_MAX); + memset (iserial, ' ', DESCR_MAX); + + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + int iManufacturer = descriptor.iManufacturer; + int iProduct = descriptor.iProduct; + int iSerialNumber = descriptor.iSerialNumber; + + if (iManufacturer) { + ret = libusb_get_string_descriptor_ascii(devh, iManufacturer, (unsigned char *)imanufact, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"manufacturer\"\n"); + strcpy(imanufact, "read error"); + } + } else + strcpy(imanufact, "not provided"); + c = strstr(imanufact, " "); + if (c) + memset((void*)c, '\0', 1); + + if (iProduct) { + ret = libusb_get_string_descriptor_ascii(devh, iProduct, (unsigned char *)iproduct, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"product\"\n"); + strcpy(iproduct, "read error"); + } + } else + strcpy(iproduct, "not provided"); + c = strstr(iproduct, " "); + if (c) + memset((void*)c, '\0', 1); + + if (iSerialNumber) { + ret = libusb_get_string_descriptor_ascii(devh, iSerialNumber, (unsigned char *)iserial, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"serial number\"\n"); + strcpy(iserial, "read error"); + } + } else + strcpy(iserial, "not provided"); + c = strstr(iserial, " "); + if (c) + memset((void*)c, '\0', 1); + fprintf(output,"-------------------------\n"); + fprintf(output,"Manufacturer: %s\n", imanufact); + fprintf(output," Product: %s\n", iproduct); + fprintf(output," Serial No.: %s\n", iserial); + fprintf(output,"-------------------------\n"); +} + + +/* Auxiliary function used by the wrapper */ +int findMBIMConfig(int vendor, int product, int mode) +{ + struct libusb_device **devs; + int resultConfig=0; + int i=0, j; + + if (libusb_get_device_list(ctx, &devs) < 0) { + perror("Libusb could not access USB. Abort"); + return 0; + } + + SHOW_PROGRESS(output,"Search USB devices ...\n"); + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + if (mode == SEARCH_BUSDEV) { + if ((libusb_get_bus_number(dev) != busnum) || + (libusb_get_device_address(dev) != devnum)) { + continue; + } else { + if (descriptor.idVendor != vendor) + continue; + if (product != descriptor.idProduct) + continue; + } + } + SHOW_PROGRESS(output,"Found device, search for MBIM configuration...\n"); + + // No check if there is only one configuration + if (descriptor.bNumConfigurations < 2) + return -1; + + // Checking all interfaces of all configurations + for (j=0; j<descriptor.bNumConfigurations; j++) { + struct libusb_config_descriptor *config; + + libusb_get_config_descriptor(dev, j, &config); + resultConfig = config->bConfigurationValue; + for (i=0; i<config->bNumInterfaces; i++) { + if ( config->interface[i].altsetting[0].bInterfaceClass == 2 ) + if ( config->interface[i].altsetting[0].bInterfaceSubClass == 0x0e ) { + // found MBIM interface in this configuration + libusb_free_config_descriptor(config); + return resultConfig; + } + } + libusb_free_config_descriptor(config); + } + return -1; + } + return 0; +} + + +void resetUSB () +{ + int success; + int bpoint = 0; + + if (!devh) { + fprintf(output,"Device handle empty, skip USB reset\n"); + return; + } + if (show_progress) { + fprintf(output,"Reset USB device "); + fflush(output); + } + sleep( 1 ); + do { + success = libusb_reset_device(devh); + if ( ((bpoint % 10) == 0) && show_progress ) { + fprintf(output,"."); + fflush(output); + } + bpoint++; + if (bpoint > 100) + success = 1; + } while (success < 0); + + if ( success ) { + SHOW_PROGRESS(output,"\n Device reset failed.\n"); + } else + SHOW_PROGRESS(output,"\n Device was reset\n"); +} + + +int switchSendMessage () +{ + const char* cmdHead = "55534243"; + int ret, i; +/* char* msg[3]; + msg[0] = MessageContent; + msg[1] = MessageContent2; + msg[2] = MessageContent3; +*/ + SHOW_PROGRESS(output,"Set up interface %d\n", Interface); + ret = libusb_claim_interface(devh, Interface); + if (ret != 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret); + return 0; + } + libusb_clear_halt(devh, MessageEndpoint); + SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint); + if (show_progress) + fflush(stdout); + + for (i=0; i<MSG_DIM; i++) { + if ( strlen(Messages[i]) == 0) + break; + + if ( sendMessage(Messages[i], i+1) ) + goto skip; + + if ( strstr(Messages[i],cmdHead) != NULL ) { + // UFI command + SHOW_PROGRESS(output,"Read the response to message %d (CSW) ...\n", i+1); + ret = read_bulk(ResponseEndpoint, ByteString, 13); + if (ret >= 0) + SHOW_PROGRESS(output,", status %d",ByteString[12]); + } else { + // Other bulk transfer + SHOW_PROGRESS(output,"Read the response to message %d ...\n", i+1); + ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 ); + } + SHOW_PROGRESS(output,"\n"); + if (ret < 0) + goto skip; + } + + SHOW_PROGRESS(output,"Reset response endpoint 0x%02x\n", ResponseEndpoint); + ret = libusb_clear_halt(devh, ResponseEndpoint); + if (ret) + SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret); + SHOW_PROGRESS(output,"Reset message endpoint 0x%02x\n", MessageEndpoint); + ret = libusb_clear_halt(devh, MessageEndpoint); + if (ret) + SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret); + usleep(50000); + + if (ReleaseDelay) { + SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay); + usleep(ReleaseDelay*1000); + } + ret = libusb_release_interface(devh, Interface); + if (ret) + goto skip; + return 1; + +skip: + SHOW_PROGRESS(output," Device is gone, skip any further commands\n"); + libusb_close(devh); + devh = NULL; + return 2; +} + + +int switchConfiguration () +{ + int ret, count = SWITCH_CONFIG_MAXTRIES; + + SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration); + while (((ret = libusb_set_configuration(devh, Configuration)) < 0) && --count) { + SHOW_PROGRESS(output," Device is busy, try to detach kernel driver\n"); + detachDriver(); + } + if (ret < 0 ) { + SHOW_PROGRESS(output," Changing the configuration failed (error %d). Try to continue\n", ret); + return 0; + } else { + SHOW_PROGRESS(output," OK, configuration set\n"); + return 1; + } +} + + +int switchAltSetting () +{ + int ret; + SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting); + ret = libusb_claim_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip AltSetting\n", ret); + return 0; + } + ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting); + libusb_release_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Change to alt setting returned error %d. Try to continue\n", ret); + return 0; + } else + return 1; +} + + +void switchHuaweiMode () +{ + int ret; + SHOW_PROGRESS(output,"Send old Huawei control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, buffer, 0, 1000); + + if (ret != 0) { + fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchSierraMode () +{ + int ret; + SHOW_PROGRESS(output,"Send Sierra control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + LIBUSB_REQUEST_SET_INTERFACE, 00000001, 0, buffer, 0, 1000); + if (ret == LIBUSB_ERROR_PIPE) { + SHOW_PROGRESS(output," communication with device stopped. May have switched modes anyway\n"); + return; + } + if (ret < 0) { + fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchGCTMode () +{ + int ret; + ret = libusb_claim_interface(devh, Interface); + if (ret != 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret); + return; + } + SHOW_PROGRESS(output,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d", + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN); + + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, + 0xa0, 0, Interface, buffer, 1, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," GCT control message 1 failed (error %d), continue anyway ...\n", ret); + } + SHOW_PROGRESS(output,"Send GCT control message 2 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, + 0xfe, 0, Interface, buffer, 1, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," GCT control message 2 failed (error %d). Abort\n\n", ret); + } + libusb_release_interface(devh, Interface); + if (ret < 0) + exit(0); +} + + +void switchKobilMode() { + int ret; + SHOW_PROGRESS(output,"Send Kobil control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0x88, 0, 0, buffer, 8, 1000); + + if (ret < 0) { + fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchQisdaMode () { + int ret; + SHOW_PROGRESS(output,"Sending Qisda control message ...\n"); + memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16); + ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, buffer, 16, 1000); + if (ret < 0) { + fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchQuantaMode() { + int ret; + SHOW_PROGRESS(output,"Send Quanta control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xff, 0, 0, buffer, 0, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchBlackberryMode () +{ + int ret; + SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xb1, 0x0000, 0, buffer, 8, 1000); + + if (ret != 8) { + fprintf(stderr, "Error: Blackberry control message 1 failed (result %d)\n", ret); + } + SHOW_PROGRESS(output,"Send Blackberry control message 2 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xa9, 0x000e, 0, buffer, 2, 1000); + + if (ret != 2) { + fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchPantechMode() +{ + int ret; + SHOW_PROGRESS(output,"Send Pantech control message, wValue %d ...\n", PantechMode); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + 0x70, PantechMode, 0, buffer, 0, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +#define EP_OUT 0x02 +#define EP_IN 0x81 +#define SIZE 0x08 + +#define MOBILE_ACTION_READLOOP1 63 +#define MOBILE_ACTION_READLOOP2 73 + +/* The code here is statically derived from sniffing (and confirmed working). + * However I bet it could be simplified significantly. + */ + +void switchActionMode () +{ + int ret, i; + SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n"); + memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE); + libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + 0x09, 0x0300, 0, buffer, SIZE, 1000); + + memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE); + libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + 0x09, 0x0300, 0, buffer, SIZE, 1000); + + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + for (i=0; i < MOBILE_ACTION_READLOOP1; i++) { + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + } + memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + for (i=0; i < MOBILE_ACTION_READLOOP2; i++) { + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + } + memcpy(buffer, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE); + ret = usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + if (ret < 0) { + SHOW_PROGRESS(output," MobileAction control sequence did not complete\n" + " Last error was %d\n",ret); + } else { + SHOW_PROGRESS(output," MobileAction control sequence complete\n"); + } +} + + +#define SQN_SET_DEVICE_MODE_REQUEST 0x0b +#define SQN_GET_DEVICE_MODE_REQUEST 0x0a + +#define SQN_DEFAULT_DEVICE_MODE 0x00 +#define SQN_MASS_STORAGE_MODE 0x01 +#define SQN_CUSTOM_DEVICE_MODE 0x02 + +void switchSequansMode() +{ + + int ret; + SHOW_PROGRESS(output,"Send Sequans control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_OUT, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE, + 0, buffer, 0, 1000); + + if (ret < 0) { + fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchCiscoMode() +{ + int ret, i, j; + + strcpy(Messages[0],"55534243f83bcd810002000080000afd000000030000000100000000000000"); + strcpy(Messages[1],"55534243984300820002000080000afd000000070000000100000000000000"); + strcpy(Messages[2],"55534243984300820000000000000afd000100071000000000000000000000"); + strcpy(Messages[3],"55534243984300820002000080000afd000200230000000100000000000000"); + strcpy(Messages[4],"55534243984300820000000000000afd000300238200000000000000000000"); + strcpy(Messages[5],"55534243984300820002000080000afd000200260000000100000000000000"); + strcpy(Messages[6],"55534243984300820000000000000afd00030026c800000000000000000000"); + strcpy(Messages[7],"55534243d84c04820002000080000afd000010730000000100000000000000"); + strcpy(Messages[8],"55534243d84c04820002000080000afd000200240000000100000000000000"); + strcpy(Messages[9],"55534243d84c04820000000000000afd000300241300000000000000000000"); + strcpy(Messages[10],"55534243d84c04820000000000000afd000110732400000000000000000000"); + + SHOW_PROGRESS(output,"Set up Cisco interface %d\n", Interface); + ret = libusb_claim_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret); + abortExit(); + } +// libusb_clear_halt(devh, MessageEndpoint); + if (show_progress) + fflush(output); + +// ret = read_bulk(ResponseEndpoint, ByteString, 13); +// SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret); + + for (i=0; i<11; i++) { + if ( sendMessage(Messages[i], i+1) ) + goto skip; + + for (j=1; j<4; j++) { + + SHOW_PROGRESS(output," Read the CSW for bulk message %d (attempt %d) ...\n",i+1,j); + ret = read_bulk(ResponseEndpoint, ByteString, 13); + SHOW_PROGRESS(output,"\n"); + + if (ret < 0) + goto skip; + if (ret == 13) + break; + } + } + libusb_clear_halt(devh, MessageEndpoint); + libusb_clear_halt(devh, ResponseEndpoint); + + ReleaseDelay = 2000; + SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay); + usleep(ReleaseDelay*1000); + + ret = libusb_release_interface(devh, Interface); + if (ret < 0) + goto skip; + return; + +skip: + SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret); + libusb_close(devh); + devh = NULL; +} + + +int switchSonyMode () +{ + int ret, i, found; + detachDriver(); + + if (CheckSuccess) { + CheckSuccess = 0; + } + + SHOW_PROGRESS(output,"Send Sony control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100); + + if (ret < 0) { + fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret); + exit(0); + } else + SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n"); + + libusb_close(devh); + devh = NULL; + + /* Now waiting for the device to reappear */ + devnum=-1; + busnum=-1; + i=0; + dev = 0; + while ( dev == 0 && i < 30 ) { + if ( i > 5 ) { + dev = search_devices(&found, DefaultVendor, DefaultProductList, TargetClass, + 0, SEARCH_TARGET); + } + if ( dev != 0 ) + break; + sleep(1); + if (show_progress) { + fprintf(output,"#"); + fflush(stdout); + } + i++; + } + SHOW_PROGRESS(output,"\n After %d seconds:",i); + if ( dev ) { + SHOW_PROGRESS(output," device came back, proceed\n"); + libusb_open(dev, &devh); + if (devh == 0) { + fprintf(stderr, "Error: could not get handle on device\n"); + return 0; + } + } else { + SHOW_PROGRESS(output," device still gone, abort\n"); + return 0; + } + sleep(1); + + SHOW_PROGRESS(output,"Send Sony control message again ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100); + + if (ret < 0) { + fprintf(stderr, "Error: Sony control message (2) failed (error %d)\n", ret); + return 0; + } + SHOW_PROGRESS(output," OK, control message sent\n"); + return 1; +} + + +/* Detach driver + */ +int detachDriver() +{ + + int ret; + SHOW_PROGRESS(output,"Looking for active driver ...\n"); + ret = libusb_kernel_driver_active(devh, 0); + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) { + fprintf(output," Can't do driver detection on this platform.\n"); + return 2; + } + if (ret < 0) { + fprintf(output," Driver check failed with error %d. Try to continue\n", ret); + return 2; + } + if (ret == 0) { + SHOW_PROGRESS(output," No active driver found. Detached before or never attached\n"); + return 1; + } + + ret = libusb_detach_kernel_driver(devh, Interface); + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) { + fprintf(output," Can't do driver detaching on this platform.\n"); + return 2; + } + if (ret == 0) { + SHOW_PROGRESS(output," OK, driver detached\n"); + } else + SHOW_PROGRESS(output," Driver detach failed (error %d). Try to continue\n", ret); + return 1; +} + + +int sendMessage(char* message, int count) +{ + int ret, message_length; + + if (strlen(message) % 2 != 0) { + fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count); + return 1; + } + message_length = strlen(message) / 2; + if ( hexstr2bin(message, ByteString, message_length) == -1) { + fprintf(stderr, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", + count, MessageContent); + + return 1; + } + SHOW_PROGRESS(output,"Trying to send message %d to endpoint 0x%02x ...\n", count, MessageEndpoint); + fflush(output); + ret = write_bulk(MessageEndpoint, ByteString, message_length); + if (ret == LIBUSB_ERROR_NO_DEVICE) + return 1; + + return 0; +} + + +int checkSuccess() +{ + int ret, i; + int newTargetCount, success=0; + + SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess); + sleep(1); + + /* If target parameters are given, don't check for vanished device + * Changed for Cisco AM10 where a new device is added while the install + * storage device stays active + */ + if ((TargetVendor || TargetClass) && devh) { + libusb_close(devh); + devh = NULL; + } + + /* if target ID is not given but target class is, assign default as target; + * it will be needed for sysmode output + */ + if (!TargetVendor && TargetClass) { + TargetVendor = DefaultVendor; + TargetProduct = DefaultProduct; + } + + /* devh is 0 if device vanished during command transmission or if target params were given + */ + if (devh) + for (i=0; i < CheckSuccess; i++) { + + /* Test if default device still can be accessed; positive result does + * not necessarily mean failure + */ + SHOW_PROGRESS(output," Wait for original device to vanish ...\n"); + + ret = libusb_claim_interface(devh, Interface); + libusb_release_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n"); + libusb_close(devh); + devh = NULL; + break; + } + if (i == CheckSuccess-1) { + SHOW_PROGRESS(output," Original device still present after the timeout\n\n" + "Mode switch most likely failed. Bye!\n\n"); + } else + sleep(1); + } + + if ( TargetVendor && (TargetProduct > -1 || TargetProductList[0] != '\0') ) { + + /* Recount target devices (compare with previous count) if target data is given. + * Target device on the same bus with higher device number is returned, + * description is read for syslog message + */ + for (i=i; i < CheckSuccess; i++) { + SHOW_PROGRESS(output," Search for target devices ...\n"); + dev = search_devices(&newTargetCount, TargetVendor, TargetProductList, + TargetClass, 0, SEARCH_TARGET); + + if (dev && (newTargetCount > targetDeviceCount)) { + if (verbose) { + libusb_open(dev, &devh); + fprintf(output,"\nFound target device %03d on bus %03d\n", + libusb_get_device_address(dev), libusb_get_bus_number(dev)); + + fprintf(output,"\nTarget device description data\n"); + deviceDescription(); + libusb_close(devh); + devh = NULL; + } + SHOW_PROGRESS(output," Found correct target device\n\n" + "Mode switch succeeded. Bye!\n\n"); + + success = 2; + break; + } + if (i == CheckSuccess-1) { + SHOW_PROGRESS(output," No new devices in target mode or class found\n\n" + "Mode switch has failed. Bye!\n\n"); + } else + sleep(1); + } + } else + /* No target data given, rely on the vanished device */ + if (!devh) { + SHOW_PROGRESS(output," (For a better success check provide target IDs or class)\n"); + SHOW_PROGRESS(output," Original device vanished after switching\n\n" + "Mode switch most likely succeeded. Bye!\n\n"); + success = 1; + } + + switch (success) { + case 3: + if (sysmode) + syslog(LOG_NOTICE, "switched to new device, but hit libusb1 bug"); + TargetProduct = -1; + success = 1; + break; + case 2: + if (sysmode) + syslog(LOG_NOTICE, "switched to %04x:%04x on %03d/%03d", TargetVendor, + TargetProduct, busnum, devnum); + + success = 1; + break; + case 1: + if (sysmode) + syslog(LOG_NOTICE, "device seems to have switched"); + default: + ; + } + if (sysmode) + closelog(); + + return success; + +} + + +int write_bulk(int endpoint, unsigned char *message, int length) +{ + int ret = usb_bulk_io(devh, endpoint, message, length, 3000); + if (ret >= 0 ) { + SHOW_PROGRESS(output," OK, message successfully sent\n"); + } else + if (ret == LIBUSB_ERROR_NO_DEVICE) { + SHOW_PROGRESS(output," Device seems to have vanished right after sending. Good.\n"); + } else + SHOW_PROGRESS(output," Sending the message returned error %d. Try to continue\n", ret); + return ret; + +} + + +int read_bulk(int endpoint, unsigned char *buffer, int length) +{ + int ret = usb_bulk_io(devh, endpoint, buffer, length, 3000); + if (ret >= 0 ) { + SHOW_PROGRESS(output," Response successfully read (%d bytes)", ret); + } else + if (ret == LIBUSB_ERROR_NO_DEVICE) { + SHOW_PROGRESS(output," Device seems to have vanished after reading. Good."); + } else + SHOW_PROGRESS(output," Response reading failed (error %d)", ret); + return ret; + +} + + +void release_usb_device(int __attribute__((unused)) dummy) +{ + SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n"); + if (devh) + libusb_release_interface(devh, Interface); + close_all(); + exit(0); + +} + + +/* Iterates over busses and devices, counts the ones which match the given + * parameters and returns the last one of them +*/ +struct libusb_device* search_devices( int *numFound, int vendor, char* productList, + int targetClass, int configuration, int mode) +{ + char *listcopy=NULL, *token; + unsigned char buffer[2]; + int devClass, product; + struct libusb_device* right_dev = NULL; +// struct libusb_device_handle *testdevh; + struct libusb_device **devs; + int i=0; + + /* only target class given, target vendor and product assumed unchanged */ + if ( targetClass && !(vendor || strlen(productList)) ) { + vendor = DefaultVendor; + productList = DefaultProductList; + } + *numFound = 0; + + /* Sanity check */ + if (!vendor || productList == '\0') + return NULL; + + listcopy = malloc(strlen(productList)+1); + + if (libusb_get_device_list(ctx, &devs) < 0) { + perror("Libusb failed to get USB access!"); + return 0; + } + + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + if (mode == SEARCH_BUSDEV) { + if ((libusb_get_bus_number(dev) != busnum) || + (libusb_get_device_address(dev) != devnum)) + continue; + else + SHOW_PROGRESS(output," bus/device number matched\n"); + } + + if (verbose) + fprintf (output," found USB ID %04x:%04x\n", + descriptor.idVendor, descriptor.idProduct); + if (descriptor.idVendor != vendor) + continue; + if (verbose) + fprintf (output," vendor ID matched\n"); + + strcpy(listcopy, productList); + token = strtok(listcopy, ","); + while (token != NULL) { + if (strlen(token) != 4) { + SHOW_PROGRESS(output,"Error: entry in product ID list has wrong length: %s. " + "Ignored\n", token); + + goto NextToken; + } + if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) { + SHOW_PROGRESS(output,"Error: entry in product ID list is not a hex string: %s. " + "Ignored\n", token); + + goto NextToken; + } + product = 0; + product += (unsigned char)buffer[0]; + product <<= 8; + product += (unsigned char)buffer[1]; + if (product == descriptor.idProduct) { + SHOW_PROGRESS(output," product ID matched\n"); + + if (targetClass != 0) { + // TargetClass is set, check class of first interface + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + devClass = descriptor.bDeviceClass; + struct libusb_config_descriptor *config; + libusb_get_config_descriptor(dev, 0, &config); + int ifaceClass = config->interface[0].altsetting[0].bInterfaceClass; + libusb_free_config_descriptor(config); + if (devClass == 0) + devClass = ifaceClass; + else + /* Check for some quirky devices */ + if (devClass != ifaceClass) + devClass = ifaceClass; + if (devClass == targetClass) { + if (verbose) + fprintf (output," target class %02x matches\n", targetClass); + if (mode == SEARCH_TARGET) { + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } else + if (verbose) + fprintf (output," device not counted, target class reached\n"); + } else { + if (verbose) + fprintf (output," device class %02x not matching target\n", devClass); + if (mode == SEARCH_DEFAULT || mode == SEARCH_BUSDEV) { + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } + } + } else if (configuration > 0) { + // Configuration parameter is set, check device configuration + int testconfig = get_current_config_value(dev); + if (testconfig != configuration) { + if (verbose) + fprintf (output," device configuration %d not matching target\n", + testconfig); + + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } else + if (verbose) + fprintf (output," device not counted, target configuration reached\n"); + } else { + // Neither TargetClass nor Configuration are set + (*numFound)++; + right_dev = dev; + if (mode == SEARCH_BUSDEV) + break; + } + } + + NextToken: + token = strtok(NULL, ","); + } + } + if (listcopy != NULL) + free(listcopy); + return right_dev; +} + + +/* Autodetect bulk endpoints (ab) */ + +int find_first_bulk_endpoint(int direction) +{ + int i, j; + const struct libusb_interface_descriptor *alt; + const struct libusb_endpoint_descriptor *ep; + + for (j=0; j < active_config->bNumInterfaces; j++) { + alt = &(active_config->interface[j].altsetting[0]); + if (alt->bInterfaceNumber == Interface) { + for (i=0; i < alt->bNumEndpoints; i++) { + ep = &(alt->endpoint[i]); + if ( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK) + && ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == direction ) ) { + + return ep->bEndpointAddress; + } + } + } + } + return 0; +} + + +int get_current_config_value() +{ + SHOW_PROGRESS(output,"Get the current device configuration ...\n"); + if (active_config != NULL) { + libusb_free_config_descriptor(active_config); + active_config = NULL; + } + int ret = libusb_get_active_config_descriptor(dev, &active_config); + if (ret < 0) { + SHOW_PROGRESS(output," Determining the active configuration failed (error %d). Abort\n", ret); + abortExit(); + } + return active_config->bConfigurationValue; +} + + +int get_interface_class() +{ + int i; + for (i=0; i < active_config->bNumInterfaces; i++) { + if (active_config->interface[i].altsetting[0].bInterfaceNumber == Interface) + return active_config->interface[i].altsetting[0].bInterfaceClass; + } + return -1; +} + + +/* Parameter parsing */ + +char* ReadParseParam(const char* FileName, char *VariableName) +{ + static int numLines = 0; + static char* ConfigBuffer[MAXLINES]; + char *VarName, *Comment=NULL, *Equal=NULL; + char *FirstQuote, *LastQuote, *P1, *P2; + int Line=0; + unsigned Len=0, Pos=0; + char Str[LINE_DIM], *token, *configPos; + FILE *file = NULL; + + // Reading and storing input during the first call + if (numLines==0) { + if (strncmp(FileName,"##",2) == 0) { + if (verbose) fprintf(output,"\nRead long config from command line\n"); + // "Embedded" configuration data + configPos = (char*)FileName; + token = strtok(configPos, "\n"); + strncpy(Str,token,LINE_DIM-1); + } else { + if (strcmp(FileName, "stdin")==0) { + if (verbose) fprintf(output,"\nRead long config from stdin\n"); + file = stdin; + } else { + if (verbose) fprintf(output,"\nRead config file: %s\n", FileName); + file=fopen(FileName, "r"); + } + if (file==NULL) { + fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName); + abortExit(); + } else { + token = fgets(Str, LINE_DIM-1, file); + } + } + while (token != NULL && numLines < MAXLINES) { +// Line++; + Len=strlen(Str); + if (Len==0) + goto NextLine; + if (Str[Len-1]=='\n' or Str[Len-1]=='\r') + Str[--Len]='\0'; + Equal = strchr (Str, '='); // search for equal sign + Pos = strcspn (Str, ";#!"); // search for comment + Comment = (Pos==Len) ? NULL : Str+Pos; + if (Equal==NULL or ( Comment!=NULL and Comment<=Equal)) + goto NextLine; // Comment or irrelevant, don't save + Len=strlen(Str)+1; + ConfigBuffer[numLines] = malloc(Len*sizeof(char)); + strcpy(ConfigBuffer[numLines],Str); + numLines++; + NextLine: + if (file == NULL) { + token = strtok(NULL, "\n"); + if (token != NULL) + strncpy(Str,token,LINE_DIM-1); + } else + token = fgets(Str, LINE_DIM-1, file); + } + if (file != NULL) + fclose(file); + } + + // Now checking for parameters + Line=0; + while (Line < numLines) { + strcpy(Str,ConfigBuffer[Line]); + Equal = strchr (Str, '='); // search for equal sign + *Equal++ = '\0'; + + // String + FirstQuote=strchr (Equal, '"'); // search for double quote char + LastQuote=strrchr (Equal, '"'); + if (FirstQuote!=NULL) { + if (LastQuote==NULL) { + fprintf(stderr, "Error reading parameters from file %s - " + "Missing end quote:\n%s\n", FileName, Str); + + goto Next; + } + *FirstQuote=*LastQuote='\0'; + Equal=FirstQuote+1; + } + + // removes leading/trailing spaces + Pos=strspn (Str, " \t"); + if (Pos==strlen(Str)) { + fprintf(stderr, "Error reading parameters from file %s - " + "Missing variable name:\n%s\n", FileName, Str); + + goto Next; + } + while ((P1=strrchr(Str, ' '))!=NULL or (P2=strrchr(Str, '\t'))!=NULL) + if (P1!=NULL) *P1='\0'; + else if (P2!=NULL) *P2='\0'; + VarName=Str+Pos; + + Pos=strspn (Equal, " \t"); + if (Pos==strlen(Equal)) { + fprintf(stderr, "Error reading parameter from file %s - " + "Missing value:\n%s\n", FileName, Str); + + goto Next; + } + Equal+=Pos; + + if (strcmp(VarName, VariableName)==0) { // Found it + return Equal; + } + Next: + Line++; + } + + return NULL; +} + + +int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + + +int hex2byte(const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + + +int hexstr2bin(const char *hex, unsigned char *buffer, int len) +{ + int i; + int a; + const char *ipos = hex; + unsigned char *opos = buffer; + + for (i = 0; i < len; i++) { + a = hex2byte(ipos); + if (a < 0) + return -1; + *opos++ = (unsigned char) a; + ipos += 2; + } + return 0; +} + + +void close_all() +{ + int i; + if (Messages) { + for ( i = 0; i < MSG_DIM; i++ ) { + free(Messages[i]); + } + free(Messages); + } + if (active_config) + libusb_free_config_descriptor(active_config); + if (devh) + libusb_close(devh); + // libusb_exit will crash on Raspbian 7, crude protection +#ifndef __ARMEL__ + libusb_exit(NULL); +#endif + if (sysmode) + closelog(); +} + + +void abortExit() +{ + close_all(); + exit(1); +} + + +void printVersion() +{ + char* version = VERSION; + fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n" + " * Version %s (C) Josua Dietze 2016\n" + " * Based on libusb1/libusbx\n\n" + " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version); +} + + +void printHelp() +{ + fprintf(output,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n" + " -h, --help this help\n" + " -e, --version print version information and exit\n" + " -j, --find-mbim return config no. with MBIM interface, exit\n\n" + " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n" + " -p, --default-product NUM product ID of original mode (mandatory)\n" + " -V, --target-vendor NUM target mode vendor ID (optional)\n" + " -P, --target-product NUM target mode product ID (optional)\n" + " -C, --target-class NUM target mode device class (optional)\n" + " -b, --bus-num NUM system bus number of device (for hard ID)\n" + " -g, --device-num NUM system device number (for hard ID)\n" + " -m, --message-endpoint NUM direct the message transfer there (optional)\n" + " -M, --message-content <msg> message to send (hex number as string)\n" + " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n" + " -w, --release-delay NUM wait NUM ms before releasing the interface\n" + " -n, --need-response obsolete, no effect (always on)\n" + " -r, --response-endpoint NUM read response from there (optional)\n" + " -K, --std-eject send standard EJECT sequence\n" + " -d, --detach-only detach the active driver, no further action\n" + " -H, --huawei-mode apply a special procedure\n" + " -J, --huawei-new-mode apply a special procedure\n" + " -S, --sierra-mode apply a special procedure\n" + " -O, --sony-mode apply a special procedure\n" + " -G, --gct-mode apply a special procedure\n" + " -N, --sequans-mode apply a special procedure\n" + " -A, --mobileaction-mode apply a special procedure\n" + " -T, --kobil-mode apply a special procedure\n" + " -L, --cisco-mode apply a special procedure\n" + " -B, --qisda-mode apply a special procedure\n" + " -E, --quanta-mode apply a special procedure\n" + " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n" + " -Z, --blackberry-mode apply a special procedure\n" + " -U, --option-mode apply a special procedure\n" + " -R, --reset-usb reset the device after all other actions\n" + " -Q, --quiet don't show progress or error messages\n" + " -W, --verbose print all settings and debug output\n" + " -D, --sysmode specific result and syslog message\n" + " -s, --success <seconds> switching result check with timeout\n" + " -I, --inquire obsolete, no effect\n\n" + " -c, --config-file <filename> load long configuration from file\n\n" + " -t, --stdinput read long configuration from stdin\n\n" + " -f, --long-config <text> get long configuration from string\n\n" + " -i, --interface NUM select initial USB interface (default 0)\n" + " -u, --configuration NUM select USB configuration\n" + " -a, --altsetting NUM select alternative USB interface setting\n\n"); +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf new file mode 100755 index 0000000..7c68993 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf @@ -0,0 +1,31 @@ +# Configuration for the usb_modeswitch package, a mode switching tool for +# USB devices providing multiple states or modes +# +# Evaluated by the wrapper script /usr/sbin/usb_modeswitch_dispatcher +# +# To enable an option, set it to "1", "yes" or "true" (case doesn't matter) +# Everything else counts as "disable" + + +# Disable automatic mode switching globally (e.g. to access the original +# install storage) + +DisableSwitching=0 + +# Disable check for MBIM module presence and configuration globally (to aid +# special embedded environments) + +DisableMBIMGlobal=0 + +# Enable logging (results in a extensive report file in /var/log, named +# "usb_modeswitch_<interface-name>" and probably others + +EnableLogging=0 + + +# Optional increase of "delay_use" for the usb-storage driver; there are hints +# that a recent kernel default change to 1 sec. may lead to problems, particu- +# larly with USB 3.0 ports. Set this to at least 3 (seconds) in that case. +# Does nothing if the current system value is same or higher + +#SetStorageDelay=4 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a new file mode 100755 index 0000000..9813a20 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a @@ -0,0 +1,4 @@ +# HP LaserJet Professional P1102 +TargetClass=0x07 +MessageContent="555342431234567800000000000006d0000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d new file mode 100755 index 0000000..609c7a1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d @@ -0,0 +1,2 @@ +# HP hs3110 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d new file mode 100755 index 0000000..8b5a348 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d @@ -0,0 +1,2 @@ +# HP hs3120 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d new file mode 100755 index 0000000..ecb0c48 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d @@ -0,0 +1,2 @@ +# HP hs3114 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d new file mode 100755 index 0000000..b2f662d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d @@ -0,0 +1,2 @@ +# HP hs4112 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d new file mode 100755 index 0000000..ff2dcc7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d @@ -0,0 +1,2 @@ +# HP lt4225 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d new file mode 100755 index 0000000..131c9d7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d @@ -0,0 +1,2 @@ +# HP lt4226 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d new file mode 100755 index 0000000..60b7f75 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d @@ -0,0 +1,2 @@ +# HP lt4227 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d new file mode 100755 index 0000000..b9a6a13 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d @@ -0,0 +1,2 @@ +# HP lt4211 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d new file mode 100755 index 0000000..08a3290 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d @@ -0,0 +1,2 @@ +# HP lt4110 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d new file mode 100755 index 0000000..d3b8b9d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d @@ -0,0 +1,2 @@ +# HP lt4114 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 new file mode 100755 index 0000000..089c437 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 @@ -0,0 +1,4 @@ +# Quanta MU-Q101 +TargetVendor=0x0408 +TargetProduct=0xea02 +MessageContent="55534243123456780002000000000a2a000000003300000100000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 new file mode 100755 index 0000000..562377a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 @@ -0,0 +1,4 @@ +# Quanta 1KR / USB-lte 7410 +TargetVendor=0x0408 +TargetProduct=0xea16 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 new file mode 100755 index 0000000..9274941 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 @@ -0,0 +1,4 @@ +# Quanta 1K3 LTE +TargetVendor=0x0408 +TargetProduct=0xea26 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 new file mode 100755 index 0000000..5c580e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 @@ -0,0 +1,4 @@ +# Quanta MobileGenie 4G LTE, Quanta 1K6 +TargetVendor=0x0408 +TargetProductList="ea47,ea49,ea4d" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 new file mode 100755 index 0000000..3e38133 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 @@ -0,0 +1,4 @@ +# MU-Q110 +TargetVendor=0x0408 +TargetProduct=0xea03 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota new file mode 100755 index 0000000..0b18e44 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota @@ -0,0 +1,4 @@ +# Yota Router (Quanta 1QDLZZZ0ST2) +TargetVendor=0x0408 +TargetProduct=0xd009 +MessageContent="5553424312345678000000000000061b004600000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 new file mode 100755 index 0000000..3cb57a0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 @@ -0,0 +1,4 @@ +# SpeedUp SU-8500U +TargetVendor=0x0408 +TargetProduct=0xea03 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c new file mode 100755 index 0000000..be0b8dc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c @@ -0,0 +1,4 @@ +# Nokia CS-10 +TargetVendor=0x0421 +TargetProduct=0x060e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 new file mode 100755 index 0000000..b2710ad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 @@ -0,0 +1,4 @@ +# Nokia CS-15 +TargetVendor=0x0421 +TargetProduct=0x0612 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 new file mode 100755 index 0000000..80afec0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 @@ -0,0 +1,4 @@ +# Nokia CS-12 +TargetVendor=0x0421 +TargetProduct=0x0619 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d new file mode 100755 index 0000000..98818a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d @@ -0,0 +1,4 @@ +# Nokia CS-11 +TargetVendor=0x0421 +TargetProduct=0x061e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 new file mode 100755 index 0000000..465f145 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 @@ -0,0 +1,4 @@ +# Nokia CS-17 +TargetVendor=0x0421 +TargetProduct=0x0623 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 new file mode 100755 index 0000000..882893b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 @@ -0,0 +1,4 @@ +# Nokia CS-18 +TargetVendor=0x0421 +TargetProductList="0612,0629" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c new file mode 100755 index 0000000..eb5dbde --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c @@ -0,0 +1,4 @@ +# Nokia CS-19 +TargetVendor=0x0421 +TargetProductList="062d,062f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 new file mode 100755 index 0000000..5ed6a7f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 @@ -0,0 +1,4 @@ +# Nokia CS-7M-01 +TargetVendor=0x0421 +TargetProduct=0x0632 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 new file mode 100755 index 0000000..e1415b7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 @@ -0,0 +1,4 @@ +# Nokia CS-21M-02 +TargetVendor=0x0421 +TargetProduct=0x0638 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 new file mode 100755 index 0000000..25a45c7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 @@ -0,0 +1,5 @@ +# Logitech G920 Racing Wheel +MessageEndpoint=0x01 +ResponseEndpoint=0x01 +TargetClass=0x03 +MessageContent="0f00010142" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips new file mode 100755 index 0000000..74eca5a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips @@ -0,0 +1,3 @@ +# Philips (?) +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue new file mode 100755 index 0000000..b3cd0a7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue @@ -0,0 +1,4 @@ +# Vodafone MD950 (Wisue Technology) +TargetVendor=0x1dbc +TargetProduct=0x0005 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 new file mode 100755 index 0000000..e48527c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 @@ -0,0 +1,4 @@ +# Philips TalkTalk (NXP Semiconductors "Dragonfly") +TargetVendor=0x0471 +TargetProductList="1206,1234" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d new file mode 100755 index 0000000..570794f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d @@ -0,0 +1,2 @@ +# Kyocera W06K CDMA modem +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd new file mode 100755 index 0000000..7c4e229 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd @@ -0,0 +1,4 @@ +# I-O Data WMX2-U Wimax +TargetVendor=0x04bb +TargetProduct=0x0949 +MessageContent="55534243f0298d8124000000800006bc626563240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 new file mode 100755 index 0000000..9d6e469 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 @@ -0,0 +1,4 @@ +# Alcatel-Lucent ABS-T920 +TargetVendor=0x04cc +TargetProductList="2259,226e" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c new file mode 100755 index 0000000..3f6e8ab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c @@ -0,0 +1,2 @@ +# Alcatel-Lucent T930S +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e new file mode 100755 index 0000000..fe4bd3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e @@ -0,0 +1,2 @@ +# Nexperia TM TD-SCDMA +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f new file mode 100755 index 0000000..a65c5cf --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f @@ -0,0 +1,2 @@ +# Nexperia TM TD-SCDMA (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c new file mode 100755 index 0000000..871cbd8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c @@ -0,0 +1,4 @@ +# Samsung GT-B1110 +TargetVendor=0x04e8 +TargetProduct=0x6792 +MessageContent="0902200001010080fa0904000002080650000705010200020007058102000200" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a new file mode 100755 index 0000000..55977b9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a @@ -0,0 +1,6 @@ +# Samsung GT-B3730 +TargetVendor=0x04e8 +TargetProduct=0x6889 +MessageContent="55534243785634120100000080000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 new file mode 100755 index 0000000..c445158 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 @@ -0,0 +1,4 @@ +# Samsung U209 +TargetVendor=0x04e8 +TargetProduct=0x6601 +MessageContent="55534243123456780000000000000616000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 new file mode 100755 index 0000000..35e00a1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 @@ -0,0 +1,4 @@ +# Sunplus Techn. SU-3200U +TargetVendor=0x04fc +TargetProductList="0615,1240" +MessageContent="55534243123456782400000080000612000024000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff new file mode 100755 index 0000000..a73effb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff @@ -0,0 +1,7 @@ +# AVM Fritz!Wlan USB Stick N v2 +TargetVendor=0x057c +TargetProductList="8501,8502" +# Std.Eject not working +MessageContent="5553424312345678000000000000061b000000ff0000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff new file mode 100755 index 0000000..3da7f76 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff @@ -0,0 +1,7 @@ +# AVM Fritz!Wlan USB Stick N +TargetVendor=0x057c +TargetProduct=0x8401 +# Std.Eject not working +MessageContent="5553424312345678000000000000061b000000ff0000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 new file mode 100755 index 0000000..d7db758 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 @@ -0,0 +1,4 @@ +# Axesstel Modems (w/ initial idProduct 0x0010) +TargetVendor=0x05c6 +TargetProduct=0x00a0 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT new file mode 100755 index 0000000..330d07c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT @@ -0,0 +1,4 @@ +# Option GlobeTrotter GX0201 +TargetVendor=0x0af0 +TargetProduct=0x6701 +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option new file mode 100755 index 0000000..c76cde8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option @@ -0,0 +1,4 @@ +# Older Option devices +TargetVendor= 0x0af0 +TargetProductList="6901,6701,6600" +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA new file mode 100755 index 0000000..ea414de --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA @@ -0,0 +1,4 @@ +# AnyDATA devices, Bless UC165 +TargetVendor= 0x16d5 +TargetProduct=0x6502 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT new file mode 100755 index 0000000..044da01 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT @@ -0,0 +1,4 @@ +# Celot K-300 a.o. +TargetVendor=0x211f +TargetProductList="6801,6802" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd new file mode 100755 index 0000000..a4e70e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd @@ -0,0 +1,4 @@ +# TechFaith Venus VT-18 +TargetVendor=0x1d09 +TargetProduct=0x4306 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT new file mode 100755 index 0000000..8a787a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT @@ -0,0 +1,4 @@ +# Celot CT-680 +TargetVendor=0x211f +TargetProduct=0x6802 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option new file mode 100755 index 0000000..0f2ce47 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option @@ -0,0 +1,4 @@ +# Quirky Option devices +TargetVendor=0x0af0 +TargetProduct=0x6901 +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG new file mode 100755 index 0000000..bbd8a30 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG @@ -0,0 +1,4 @@ +# Samsung SGH-Z810 +TargetVendor= 0x04e8 +TargetProduct=0x6601 +MessageContent="55534243123456780000000000000616000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE new file mode 100755 index 0000000..8ed06ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE @@ -0,0 +1,4 @@ +# Prolink P2000 CDMA +TargetVendor=0x05c6 +TargetProduct=0x6000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising new file mode 100755 index 0000000..171cae3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising @@ -0,0 +1,4 @@ +# StrongRising device +TargetVendor= 0x028a +TargetProduct=0x1006 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex new file mode 100755 index 0000000..8fbcd80 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex @@ -0,0 +1,4 @@ +# Vertex Wireless 100 Series +TargetVendor=0x1fe7 +TargetProduct=0x0100 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 new file mode 100755 index 0000000..65897a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 @@ -0,0 +1,6 @@ +# Various USB modems +TargetVendor=0x05c6 +TargetProductList="0015,0016,0018,ce17" +MessageContent="5553424368032c882400000080000612000000240000000000000000000000" +NeedResponse=1 +CheckSuccess=40 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 new file mode 100755 index 0000000..f13efd9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 @@ -0,0 +1,4 @@ +# D-Link DWM-162-U5, DWM-162 C1, Micromax MMX 300c +TargetVendor=0x1e0e +TargetProductList="ce16,ce17,cefe" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 new file mode 100755 index 0000000..43c6217 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 @@ -0,0 +1,4 @@ +# AnyDATA APE-540H +TargetVendor=0x16d5 +TargetProduct=0x6502 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 new file mode 100755 index 0000000..c809a67 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 @@ -0,0 +1,4 @@ +# Alcatel-sbell ASB TL131 TD-LTE +TargetVendor=0x05c6 +TargetProduct=0x9025 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff new file mode 100755 index 0000000..72e252a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff @@ -0,0 +1,4 @@ +# U901 (LTE modem) +TargetVendor=0x05c6 +TargetProduct=0x6001 +SierraMode=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 new file mode 100755 index 0000000..d064949 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 @@ -0,0 +1,5 @@ +# Siptune LM-75 ("LinuxModem"), EWangshikong 4G +TargetVendor=0x05c6 +TargetProductList="0016,6000,9000" +StandardEject=1 +MessageContent="5553424308306384c000000080000671030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 new file mode 100755 index 0000000..9db6c68 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 @@ -0,0 +1,4 @@ +# Qtronix EVDO 3G Modem (for TianYi) +TargetVendor=0x05c7 +TargetProduct=0x6000 +MessageContent="5553424312345678c00000008000069f140000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 new file mode 100755 index 0000000..d0b85b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 @@ -0,0 +1,5 @@ +# ZE-3G 7.2Mbs HSPA modem +TargetVendor=0x1c9e +TargetProduct=0x9603 +MessageContent="5553424368032c882400000080000612000000240000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d new file mode 100755 index 0000000..95f7c45 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d @@ -0,0 +1,7 @@ +# InfoCert Business Key (SmartCard/Reader emulation) +TargetVendor=0x072f +TargetProduct=0x90cc +MessageEndpoint=0x02 +MessageContent="01b0000000000000000000000000000000000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 new file mode 100755 index 0000000..2adc178 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 @@ -0,0 +1,4 @@ +# D-Link DWM-156 HSUPA 3.75G a.o. +TargetVendor=0x07d1 +TargetProductList="3e01,3e02,7e0c" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 new file mode 100755 index 0000000..6fced74 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 @@ -0,0 +1,4 @@ +# D-Link DWM-156 HSUPA 3.75G USB Modem +TargetVendor=0x07d1 +TargetProduct=0x7e11 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 new file mode 100755 index 0000000..f79dba7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 @@ -0,0 +1,4 @@ +# D-Link DWM-151 A1 +TargetVendor=0x07d1 +TargetProduct=0x7e07 +MessageContent="555342431234567800000000000006bd000000020000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 new file mode 100755 index 0000000..86886a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 @@ -0,0 +1,8 @@ +# Dymo LabelManager +TargetVendor=0x0922 +TargetProduct=0x1002 +MessageEndpoint=0x01 +ResponseEndpoint=0x01 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 new file mode 100755 index 0000000..82f42e3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 @@ -0,0 +1,6 @@ +# Dymo LabelManager 420P +TargetVendor= 0x0922 +TargetProduct= 0x1004 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 new file mode 100755 index 0000000..2b48fb0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 @@ -0,0 +1,6 @@ +# Dymo LabelManager Wireless PnP +TargetVendor= 0x0922 +TargetProduct= 0x1008 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 new file mode 100755 index 0000000..2dcca74 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 @@ -0,0 +1,4 @@ +# Toshiba G450 +TargetVendor=0x0930 +TargetProduct=0x0d45 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 new file mode 100755 index 0000000..9b5a78f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 @@ -0,0 +1,4 @@ +# Zydas ZD1211RW WLAN USB, Sphairon HomeLink 1202 (Variant 1) +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff new file mode 100755 index 0000000..55178af --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff @@ -0,0 +1,4 @@ +# Zydas ZD1211RW WLAN USB, Sphairon HomeLink 1202 (Variant 2) +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 new file mode 100755 index 0000000..d209494 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 @@ -0,0 +1,6 @@ +# Option iCon 711 +TargetVendor=0x0af0 +TargetProduct=0x4005 +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 new file mode 100755 index 0000000..ffaea9c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 @@ -0,0 +1,5 @@ +# Option iCon 461 +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 new file mode 100755 index 0000000..ccdd7f5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 @@ -0,0 +1,6 @@ +# Option Globetrotter (Variant) +TargetVendor=0x0af0 +TargetProduct=0x9100 +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 new file mode 100755 index 0000000..2d73b1c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 @@ -0,0 +1,5 @@ +# Option GI0643 (aka XYFI) +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 new file mode 100755 index 0000000..4f2b39e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 @@ -0,0 +1,6 @@ +# Option GlobeTrotter GI1515 +TargetVendor=0x0af0 +TargetProductList="d157,d255,d257" +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 new file mode 100755 index 0000000..fd4da50 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 @@ -0,0 +1,4 @@ +# Olivetti Olicard 100 and others +TargetVendor=0x0b3c +TargetProductList="c000,c001,c002" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 new file mode 100755 index 0000000..b17d1eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 @@ -0,0 +1,5 @@ +# Olivetti Olicard 145, 155 +TargetVendor=0x0b3c +TargetProductList="c003,c004" +MessageContent="5553424312345678c000000080010606f50402527000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c new file mode 100755 index 0000000..00f1298 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c @@ -0,0 +1,4 @@ +# Olivetti Olicard 160 +TargetVendor=0x0b3c +TargetProduct=0xc00a +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 new file mode 100755 index 0000000..72df51d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 @@ -0,0 +1,4 @@ +# Olivetti Olicard 500 +TargetVendor=0x0b3c +TargetProduct=0xc00b +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d new file mode 100755 index 0000000..aa901b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d @@ -0,0 +1,2 @@ +# Ericsson F5521gw +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 new file mode 100755 index 0000000..5e9049e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 @@ -0,0 +1,2 @@ +# Ericsson F5521gw (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff new file mode 100755 index 0000000..3ce9058 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff @@ -0,0 +1,6 @@ +# Atheros Wireless / Netgear WNDA3200 +TargetVendor=0x0cf3 +TargetProduct=0x7010 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 new file mode 100755 index 0000000..1d82e3f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 @@ -0,0 +1,4 @@ +# Kobil mIdentity 3G (1) +TargetVendor=0x0d46 +TargetProduct=0x45a9 +KobilMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 new file mode 100755 index 0000000..2074a95 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 @@ -0,0 +1,4 @@ +# Kobil mIdentity 3G (2) +TargetVendor=0x0d46 +TargetProduct=0x45ad +KobilMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 new file mode 100755 index 0000000..826501c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 @@ -0,0 +1,5 @@ +# Mobile Action ("Smart Cable") +TargetClass=0xff +MobileActionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT new file mode 100755 index 0000000..f23f468 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT @@ -0,0 +1,4 @@ +# MediaTek MT6276M and others +TargetVendor=0x0e8d +TargetProductList="00a1,00a2,00a5" +MessageContent="555342431234567800000000000006f0010300000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product new file mode 100755 index 0000000..f36fa83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product @@ -0,0 +1,4 @@ +# MediaTek/Medion S4222 and probably others +TargetVendor=0x0e8d +TargetProductList="00a1,00a2,00a5" +MessageContent="555342431234567800000000000006f0010300000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 new file mode 100755 index 0000000..a71557f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 @@ -0,0 +1,6 @@ +# MediaTek Wimax USB Card +TargetVendor=0x0e8d +TargetProductList="7115,7118" +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 new file mode 100755 index 0000000..7a07ad9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 @@ -0,0 +1,4 @@ +# BlackBerry Q10 and Z10 +TargetVendor=0x0fca +TargetProduct=0x8012 +BlackberryMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf new file mode 100755 index 0000000..85dc2c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf @@ -0,0 +1,2 @@ +# Sony Ericsson MD300 +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df new file mode 100755 index 0000000..4bb9dca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df @@ -0,0 +1,2 @@ +# Sony Ericsson EC400 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 new file mode 100755 index 0000000..f3e9e86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 @@ -0,0 +1,4 @@ +# Sony Ericsson MD400 +TargetClass=0x02 +SonyMode=1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 new file mode 100755 index 0000000..cc9e7a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 @@ -0,0 +1,4 @@ +# Sony Ericsson MD400G +TargetClass=0x02 +SonyMode=1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 new file mode 100755 index 0000000..04101aa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 @@ -0,0 +1,2 @@ +# GW D301 (Advinne AMC) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 new file mode 100755 index 0000000..4468271 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 @@ -0,0 +1,3 @@ +# LG LDU-1900D EV-DO (Rev. A) +TargetClass=0xff +MessageContent="55534243123456780000000000000aff554d53434847000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f new file mode 100755 index 0000000..25ccde5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f @@ -0,0 +1,5 @@ +# LG HDM-2100 (EVDO Rev.A USB modem) +TargetVendor=0x1004 +TargetProductList="6000,6114" +MessageContent="555342431234567803000000800006f1010100000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c new file mode 100755 index 0000000..dc25e1f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c @@ -0,0 +1,4 @@ +# LG L-02A +TargetVendor=0x1004 +TargetProduct=0x6109 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a new file mode 100755 index 0000000..02bc44b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a @@ -0,0 +1,4 @@ +# LG L-05A +TargetVendor=0x1004 +TargetProduct=0x6124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f new file mode 100755 index 0000000..ce75c58 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f @@ -0,0 +1,4 @@ +# LG LUU-2100TI (aka AT&T USBConnect Turbo) +TargetVendor=0x1004 +TargetProduct=0x6141 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e new file mode 100755 index 0000000..0492200 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e @@ -0,0 +1,4 @@ +# LG L-07A +TargetVendor=0x1004 +TargetProduct=0x6135 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 new file mode 100755 index 0000000..89b1b85 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 @@ -0,0 +1,4 @@ +# LG LUU-2110TI +TargetVendor=0x1004 +TargetProduct=0x6157 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 new file mode 100755 index 0000000..4334c0a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 @@ -0,0 +1,5 @@ +# LG AD600 +TargetVendor=0x1004 +TargetProduct=0x61a7 +WaitBefore=10 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa new file mode 100755 index 0000000..0db0efb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa @@ -0,0 +1,4 @@ +# LG VL600 +TargetVendor=0x1004 +TargetProduct=0x61a7 +StandardEject=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd new file mode 100755 index 0000000..2ccd9bc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd @@ -0,0 +1,4 @@ +# LG L-02C LTE +TargetVendor=0x1004 +TargetProduct=0x618f +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 new file mode 100755 index 0000000..097e7e2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 @@ -0,0 +1,4 @@ +# LG SD711 +TargetVendor=0x1004 +TargetProduct=0x61e6 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb new file mode 100755 index 0000000..10f1591 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb @@ -0,0 +1,4 @@ +# LG L-08C (NTT docomo) +TargetVendor=0x1004 +TargetProduct=0x61ea +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 new file mode 100755 index 0000000..f34ce2a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 @@ -0,0 +1,4 @@ +# LG L-03D LTE/3G +TargetVendor=0x1004 +TargetProduct=0x6326 +MessageContent=555342431234567800000000000005f1010100000000000000000000000000 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 new file mode 100755 index 0000000..2541fd2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 @@ -0,0 +1,4 @@ +# Huawei E630 +TargetVendor=0x12d1 +TargetProduct=0x1003 +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 new file mode 100755 index 0000000..4201228 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 @@ -0,0 +1,4 @@ +# UTStarcom UM175 (distributor "Alltel") +TargetVendor=0x106c +TargetProduct=0x3715 +MessageContent="555342431234567824000000800008ff024445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 new file mode 100755 index 0000000..e7f732d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 @@ -0,0 +1,4 @@ +# Pantech / UTStarcom UMW190 (Verizon) +TargetVendor=0x106c +TargetProduct=0x3716 +MessageContent="555342431234567824000000800008ff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 new file mode 100755 index 0000000..9351e41 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 @@ -0,0 +1,4 @@ +# UTStarcom UM185E (distributor "Alltel") +TargetVendor=0x106c +TargetProduct=0x3717 +MessageContent="55534243b82e238c24000000800008ff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 new file mode 100755 index 0000000..7ebbf49 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 @@ -0,0 +1,4 @@ +# Pantech UML290 +TargetVendor=0x106c +TargetProduct=0x3718 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 new file mode 100755 index 0000000..eb351af --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 @@ -0,0 +1,6 @@ +# Option Beemo / Pantech P4200 LTE +TargetVendor=0x106c +TargetProduct=0x3721 +MessageContent="555342431234567824000000800008ff024445564348470000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 new file mode 100755 index 0000000..60e9117 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 @@ -0,0 +1,4 @@ +# Sagem F@ST 9520-35-GLR +TargetVendor=0x1076 +TargetProduct=0x7f00 +GCTMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 new file mode 100755 index 0000000..7d1e2c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 @@ -0,0 +1,4 @@ +# Hisense E910 EVDO Phone +TargetVendor=0x109b +TargetProduct=0x9114 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f new file mode 100755 index 0000000..45dda80 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f @@ -0,0 +1,7 @@ +# Pantech/Verizon UML295 +TargetVendor=0x10a9 +TargetProductList="6064,6074" +# Use 1 for automatic choice, 2 for RNDIS, 4 for QMI +PantechMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 new file mode 100755 index 0000000..3883005 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 @@ -0,0 +1,4 @@ +# Pantech LTE Modem +TargetVendor=0x10a9 +TargetProduct=0x6085 +PantechMode=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff new file mode 100755 index 0000000..88c8882 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff @@ -0,0 +1,6 @@ +# Sierra devices (specific driver) +TargetVendor= 0x1199 +TargetProductList="0017,0018,0019,0020,0021,0022,0023,0024,0025,0026,0027,0028,0029,0112,0120,0218,0220,0224,0301,6802,6803,6804,6805,6808,6809,6812,6813,6815,6816,6820,6821,6822,6832,6833,6834,6835,6838,6839,683a,683b,683c,683d,683e,6850,6851,6852,6853,6855,6856,6859,685a,6880,6890,6891,6892,6893,68a2,68a3,68aa,9011,9012,9051" +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 new file mode 100755 index 0000000..e1ac1fe --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 @@ -0,0 +1,4 @@ +# Sierra MC8305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 new file mode 100755 index 0000000..d60fac0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 @@ -0,0 +1,4 @@ +# Sierra MC8355 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 new file mode 100755 index 0000000..d33a899 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 @@ -0,0 +1,4 @@ +# Sierra MC8355 Variant +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b new file mode 100755 index 0000000..f291e83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b @@ -0,0 +1,4 @@ +# Sierra MC7770 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c new file mode 100755 index 0000000..3a13e2f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c @@ -0,0 +1,4 @@ +# Sierra EM7700 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f new file mode 100755 index 0000000..ca03f4c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f @@ -0,0 +1,4 @@ +# Sierra EM7355 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 new file mode 100755 index 0000000..2389f40 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 @@ -0,0 +1,4 @@ +# Sierra EM7305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 new file mode 100755 index 0000000..0e10ef2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 @@ -0,0 +1,4 @@ +# Sierra AC340U +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 new file mode 100755 index 0000000..debd945 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 @@ -0,0 +1,4 @@ +# Sierra AC770S +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 new file mode 100755 index 0000000..2389f40 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 @@ -0,0 +1,4 @@ +# Sierra EM7305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 new file mode 100755 index 0000000..cf859d0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 @@ -0,0 +1,4 @@ +# Digicom 8E4455 (and all Pirelli devices - EXPERIMENTAL) +TargetVendor=0x1266 +TargetProductList="1002,1003,1004,1005,1006,1007,1008,1009,100a,100b,100c,100d,100e,100f,1011,1012" +StandardEject=1 diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" new file mode 100755 index 0000000..f7d7928 --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" @@ -0,0 +1,3 @@ +# Huawei generic for Android +TargetVendor= 0x12d1 +MessageContent="55534243123456780000000000000011063000000100010000000000000000" diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" new file mode 100755 index 0000000..78e7ea5 --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" @@ -0,0 +1,3 @@ +# Huawei generic for Linux (fall-back for unknown products) +TargetVendor= 0x12d1 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 new file mode 100755 index 0000000..273c035 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 @@ -0,0 +1,3 @@ +# Huawei E169 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 new file mode 100755 index 0000000..5c37062 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 @@ -0,0 +1,3 @@ +# Huawei E220, E230, E270, E870 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 new file mode 100755 index 0000000..2b03464 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 @@ -0,0 +1,3 @@ +# Huawei V725 Phone (aka Vodafone 725) +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 new file mode 100755 index 0000000..c7c1d03 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 @@ -0,0 +1,3 @@ +# Huawei ETS1201 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e new file mode 100755 index 0000000..dae8e2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e @@ -0,0 +1,3 @@ +# Huawei U7510 / U7517 +TargetClass=0xff +MessageContent="55534243123456780600000080000601000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 new file mode 100755 index 0000000..d5c73d7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 @@ -0,0 +1,6 @@ +# Huawei U8220, T-Mobile Pulse (Android smartphone) +TargetVendor=0x12d1 +TargetProduct=0x1034 +MessageContent="55534243123456780600000080010a11060000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 new file mode 100755 index 0000000..cc262da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 @@ -0,0 +1,7 @@ +# Huawei U8110 / Joy, Vodafone 845 (Android smartphone) +TargetVendor=0x12d1 +TargetProduct=0x1035 +MessageContent="55534243123456780600000080010a11060000000000000000000000000000" +# for Android SDK + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 new file mode 100755 index 0000000..1158582 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 @@ -0,0 +1,3 @@ +# Huawei EC168 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 new file mode 100755 index 0000000..742d75d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 @@ -0,0 +1,3 @@ +# Huawei E180 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 new file mode 100755 index 0000000..48c6d35 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 @@ -0,0 +1,4 @@ +# Huawei, newer modems, and rebrandings +TargetVendor=0x12d1 +TargetProductList="1001,1404,1406,140b,140c,1412,1417,141b,1429,1432,1433,1436,14ac,1506,150c,1511" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 new file mode 100755 index 0000000..1713857 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 @@ -0,0 +1,4 @@ +# Huawei E352 +TargetVendor=0x12d1 +TargetProduct=0x1444 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad new file mode 100755 index 0000000..e3d4328 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K3806 +TargetVendor=0x12d1 +TargetProduct=0x14ae +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 new file mode 100755 index 0000000..322da5f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 @@ -0,0 +1,4 @@ +# Huawei E173 (Viettel 3G) +TargetVendor=0x12d1 +TargetProductList="14a8,14aa" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 new file mode 100755 index 0000000..e9f7cee --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4511 +TargetVendor=0x12d1 +TargetProduct=0x14cc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba new file mode 100755 index 0000000..a2c257e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba @@ -0,0 +1,4 @@ +# Huawei E173u-2, E177 +TargetVendor=0x12d1 +TargetProduct=0x14d2 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 new file mode 100755 index 0000000..309830f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4605 +TargetVendor=0x12d1 +TargetProduct=0x14c6 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 new file mode 100755 index 0000000..413e8d2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 @@ -0,0 +1,4 @@ +# K5005 Vodafone/Huawei +TargetVendor=0x12d1 +TargetProduct=0x14c8 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 new file mode 100755 index 0000000..e7ffc66 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 @@ -0,0 +1,4 @@ +# Vodafone/Huawei K3771 +TargetVendor=0x12d1 +TargetProduct=0x14ca +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 new file mode 100755 index 0000000..17ecd3c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4510 +TargetVendor=0x12d1 +TargetProduct=0x14cb +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 new file mode 100755 index 0000000..2ab14e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3770 +TargetVendor=0x12d1 +TargetProduct=0x14c9 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe new file mode 100755 index 0000000..9c16d2a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe @@ -0,0 +1,4 @@ +# Huawei E352 (T-Mobile NL), E173s (Variant) +TargetVendor=0x12d1 +TargetProductList="1506,150f,151d,1c1e" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 new file mode 100755 index 0000000..ab5e1cd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 @@ -0,0 +1,4 @@ +# Huawei EC156, Huawei E372u-8 +TargetVendor=0x12d1 +TargetProductList="140b,140c,1506,150f,150a" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a new file mode 100755 index 0000000..283ae5b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a @@ -0,0 +1,4 @@ +# Huawei E392u-12, E3131 (Variant) +TargetVendor=0x12d1 +TargetProductList="151b,151d,151e" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 new file mode 100755 index 0000000..d03f821 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 @@ -0,0 +1,4 @@ +# Huawei K3765 +TargetVendor=0x12d1 +TargetProduct=0x1465 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 new file mode 100755 index 0000000..620690c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 @@ -0,0 +1,4 @@ +# Huawei K4505 +TargetVendor=0x12d1 +TargetProduct=0x1464 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 new file mode 100755 index 0000000..0eb4b7a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 @@ -0,0 +1,4 @@ +# Huawei R201 +TargetVendor=0x12d1 +TargetProduct=0x1491 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 new file mode 100755 index 0000000..60b8457 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3772 +TargetVendor=0x12d1 +TargetProduct=0x14cf +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 new file mode 100755 index 0000000..84fe445 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R206 Router +TargetVendor=0x12d1 +TargetProduct=0x1594 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 new file mode 100755 index 0000000..0d2552e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 @@ -0,0 +1,4 @@ +# Huawei E1553 +TargetVendor=0x12d1 +TargetProduct=0x1001 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 new file mode 100755 index 0000000..beef342 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 @@ -0,0 +1,4 @@ +# Huawei E173 +TargetVendor=0x12d1 +TargetProduct=0x14a5 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a new file mode 100755 index 0000000..451a8f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a @@ -0,0 +1,4 @@ +# Vodafone (Huawei) R205 +TargetVendor=0x12d1 +TargetProduct=0x14cd +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b new file mode 100755 index 0000000..d10d02d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b @@ -0,0 +1,4 @@ +# Huawei E171 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a new file mode 100755 index 0000000..55e6d38 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a @@ -0,0 +1,4 @@ +# Huawei E3276s-151 and E3251 +TargetVendor=0x12d1 +TargetProductList="156b,156c" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 new file mode 100755 index 0000000..5b8ac78 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 @@ -0,0 +1,2 @@ +# Huawei ME906E +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 new file mode 100755 index 0000000..2b2eb6b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 @@ -0,0 +1,2 @@ +# Huawei EM820W +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 new file mode 100755 index 0000000..20b6e2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 @@ -0,0 +1,2 @@ +# Huawei MU733 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 new file mode 100755 index 0000000..0397c2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 @@ -0,0 +1,2 @@ +# Huawei ME909u-521 (MBIM, handled by kernel, dummy config) +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c new file mode 100755 index 0000000..35d811d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c @@ -0,0 +1,4 @@ +# Huawei E3276-s150 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d new file mode 100755 index 0000000..f42d3b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d @@ -0,0 +1,4 @@ +# Huawei E3331, E3372 +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 new file mode 100755 index 0000000..9b27048 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R210 Router +TargetVendor=0x12d1 +TargetProduct=0x1585 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 new file mode 100755 index 0000000..507ab0e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R208 Router +TargetVendor=0x12d1 +TargetProduct=0x1587 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 new file mode 100755 index 0000000..c8588a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R215 Router +TargetVendor=0x12d1 +TargetProduct=0x1588 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 new file mode 100755 index 0000000..d45b089 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 @@ -0,0 +1,4 @@ +# Vodafone / Huawei W5101 Router +TargetVendor=0x12d1 +TargetProduct=0x1589 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 new file mode 100755 index 0000000..0a91c2d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 @@ -0,0 +1,4 @@ +# Huawei E327s-150 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x1598 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb new file mode 100755 index 0000000..d6b1add --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb @@ -0,0 +1,2 @@ +# Huawei ME936 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 new file mode 100755 index 0000000..c0b7769 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 @@ -0,0 +1,2 @@ +# Huawei ME906C +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 new file mode 100755 index 0000000..24e2ec0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 @@ -0,0 +1,2 @@ +# Huawei ME906, ME909 (MBIM, handled by kernel, dummy config) +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca new file mode 100755 index 0000000..cf9da86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca @@ -0,0 +1,4 @@ +# Huawei E3131 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd new file mode 100755 index 0000000..28a5fc3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd @@ -0,0 +1,4 @@ +# Huawei E3372 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce new file mode 100755 index 0000000..3ec6ce3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce @@ -0,0 +1,4 @@ +# Huawei E3531s-2, E3131 (Variant) +TargetVendor=0x12d1 +TargetProductList="15b1,15b3" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf new file mode 100755 index 0000000..7addb2d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf @@ -0,0 +1,4 @@ +# Huawei E3372s-153 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 new file mode 100755 index 0000000..5d2ee64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 @@ -0,0 +1,4 @@ +# Huawei E3131 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x15d1 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 new file mode 100755 index 0000000..94bbbac --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 @@ -0,0 +1,4 @@ +# Huawei E3531 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x15d3 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 new file mode 100755 index 0000000..6be0d6f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 @@ -0,0 +1,4 @@ +# Huawei E3531 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 new file mode 100755 index 0000000..c98abfd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 @@ -0,0 +1,2 @@ +# Huawei MU736 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 new file mode 100755 index 0000000..d408152 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 @@ -0,0 +1,3 @@ +# Huawei U2800 Phone +TargetClass=0xff +MessageContent="55534243123456780600000080000601000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b new file mode 100755 index 0000000..c6bb69f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b @@ -0,0 +1,4 @@ +# Huawei E173s +TargetVendor=0x12d1 +TargetProductList="1c05,1c06,1c07,1c08,1c10" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b new file mode 100755 index 0000000..3773123 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b @@ -0,0 +1,6 @@ +# Huawei GP02 (E587 Variant) +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 new file mode 100755 index 0000000..3b9f196 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 @@ -0,0 +1,4 @@ +# Huawei E173 (Moviestar), E173s (Variant) +TargetVendor=0x12d1 +TargetProductList="1c12,1c23" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 new file mode 100755 index 0000000..fa88d4d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 @@ -0,0 +1,2 @@ +# Huawei MU709s-2 Module +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 new file mode 100755 index 0000000..b218355 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 @@ -0,0 +1,2 @@ +# Huawei ET302 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 new file mode 100755 index 0000000..3bb1cab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 @@ -0,0 +1,4 @@ +# Huawei ET8282, Huawei ET127 +TargetVendor=0x12d1 +TargetProduct=0x1d09 +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 new file mode 100755 index 0000000..68cea57 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 @@ -0,0 +1,6 @@ +# Huawei E353 (3.se) and others +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 new file mode 100755 index 0000000..32a87b0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 @@ -0,0 +1,6 @@ +# Huawei E5377 +TargetVendor=0x12d1 +TargetProduct=0x14dc +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 new file mode 100755 index 0000000..a9db535 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 @@ -0,0 +1,6 @@ +# KDDI (Huawei) HWD12 LTE +TargetVendor=0x12d1 +TargetProduct=0x14db +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 new file mode 100755 index 0000000..aad96a9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R206_MR Router +TargetVendor=0x12d1 +TargetProduct=0x15bc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 new file mode 100755 index 0000000..cbde895 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R207 Router +TargetVendor=0x12d1 +TargetProduct=0x15bd +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 new file mode 100755 index 0000000..844e858 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R215_MR Router +TargetVendor=0x12d1 +TargetProduct=0x15c7 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 new file mode 100755 index 0000000..0a023f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 @@ -0,0 +1,6 @@ +# Huawei/Vodafone R226 +TargetVendor=0x12d1 +TargetProduct=0x15bf +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 new file mode 100755 index 0000000..6a99608 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 @@ -0,0 +1,6 @@ +# Huawei/Vodafone R216 +TargetVendor=0x12d1 +TargetProduct=0x1c50 +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 new file mode 100755 index 0000000..0786aad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3773 +TargetVendor=0x12d1 +TargetProduct=0x14bc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 new file mode 100755 index 0000000..93de9b3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 @@ -0,0 +1,4 @@ +# Vodafone K4305 +TargetVendor=0x12d1 +TargetProductList="1400,14f7" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 new file mode 100755 index 0000000..a32d517 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 @@ -0,0 +1,4 @@ +# Vodafone K5150 +TargetVendor=0x12d1 +TargetProductList="14f8,1575" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 new file mode 100755 index 0000000..e31f0b4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 @@ -0,0 +1,4 @@ +# Vodafone K4201 +TargetVendor=0x12d1 +TargetProduct=0x1576 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 new file mode 100755 index 0000000..767644a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 @@ -0,0 +1,4 @@ +# Vodafone K4202 +TargetVendor=0x12d1 +TargetProduct=0x1577 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 new file mode 100755 index 0000000..b823b1a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 @@ -0,0 +1,4 @@ +# Vodafone K4606 +TargetVendor=0x12d1 +TargetProductList="14fa,1575,1578" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b new file mode 100755 index 0000000..6068a4c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b @@ -0,0 +1,4 @@ +# Vodafone / Huawei Kxxxx +TargetVendor=0x12d1 +TargetProduct=0x1579 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c new file mode 100755 index 0000000..cf43358 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c @@ -0,0 +1,4 @@ +# Vodafone / Huawei K4203 +TargetVendor=0x12d1 +TargetProductList="157a,1590" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d new file mode 100755 index 0000000..eb4c393 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d @@ -0,0 +1,4 @@ +# Vodafone / Huawei Kxxxx +TargetVendor=0x12d1 +TargetProductList="157b,1591" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e new file mode 100755 index 0000000..a20456a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e @@ -0,0 +1,4 @@ +# Vodafone / Huawei K5160 +TargetVendor=0x12d1 +TargetProductList="157f,1592" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b new file mode 100755 index 0000000..293ec72 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b @@ -0,0 +1,3 @@ +# Huawei BM358 WiMAX +TargetClass=0x02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 new file mode 100755 index 0000000..823c9ec --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 @@ -0,0 +1,6 @@ +# Cisco AM10 "Valet Connector" +TargetVendor=0x13b1 +TargetProduct=0x0031 +CiscoMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 new file mode 100755 index 0000000..56ec385 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 @@ -0,0 +1,4 @@ +# Novatel Wireless devices +TargetVendor=0x1410 +TargetProductList="4100,4400,7030" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 new file mode 100755 index 0000000..884787a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 @@ -0,0 +1,4 @@ +# Novatel MC990D +TargetVendor=0x1410 +TargetProductList="6000,7001" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 new file mode 100755 index 0000000..ffe9b64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 @@ -0,0 +1,4 @@ +# Novatel MC996D +TargetVendor=0x1410 +TargetProduct=0x7030 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 new file mode 100755 index 0000000..ffc730a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 @@ -0,0 +1,4 @@ +# Novatel U760 +TargetVendor=0x1410 +TargetProduct=0x6000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 new file mode 100755 index 0000000..6f0fe13 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 @@ -0,0 +1,4 @@ +# Novatel MC760 3G +TargetVendor=0x1410 +TargetProduct=0x6002 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 new file mode 100755 index 0000000..747a4ce --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 @@ -0,0 +1,4 @@ +# Novatel Generic MiFi 2352 / Vodafone MiFi 2352 +TargetVendor=0x1410 +TargetProductList="7001,7003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 new file mode 100755 index 0000000..bce995d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 @@ -0,0 +1,4 @@ +# Novatel MiFi 4082 +TargetVendor=0x1410 +TargetProduct=0x6032 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 new file mode 100755 index 0000000..e191387 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 @@ -0,0 +1,4 @@ +# Novatel Wireless MC545 HSPA, U679 LTE +TargetVendor=0x1410 +TargetProductList="7031,7042" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 new file mode 100755 index 0000000..e02f95e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 @@ -0,0 +1,3 @@ +# Novatel Generic MiFi 2372 / Vodafone MiFi 2372 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 new file mode 100755 index 0000000..ba50114 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 @@ -0,0 +1,2 @@ +# Novatel U620L +Configuration=4 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 new file mode 100755 index 0000000..6ff409b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 @@ -0,0 +1,3 @@ +# Sequans SQN1210/SQN1220 (generic chipsets) +TargetClass=0x02 +SequansMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 new file mode 100755 index 0000000..7fd5163 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 @@ -0,0 +1,6 @@ +# Motorola 802.11 bg WLAN (TER/GUSB3-E) +TargetVendor=0x148f +TargetProduct=0x9021 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 new file mode 100755 index 0000000..2969bd8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 @@ -0,0 +1,4 @@ +# China TeleCom CBP7.0 +TargetVendor=0x15eb +TargetProduct=0x7152 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 new file mode 100755 index 0000000..9dd94a0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 @@ -0,0 +1,5 @@ +# Amoi H-01 +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 new file mode 100755 index 0000000..67d5946 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 @@ -0,0 +1,5 @@ +# Amoi H-02 +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 new file mode 100755 index 0000000..b140d0f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 @@ -0,0 +1,4 @@ +# Anydata ADU-890WH +TargetVendor=0x16d5 +TargetProduct=0x6603 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 new file mode 100755 index 0000000..97c0773 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 @@ -0,0 +1,3 @@ +# C-motech CHU-628S +TargetClass=0xff +MessageContent="555342431234567824000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 new file mode 100755 index 0000000..bbe9bca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 @@ -0,0 +1,3 @@ +# C-motech D-50 (aka "CDU-680", "CNU-680") +TargetClass=0x02 +MessageContent="555342431234567824000000800008ff524445564348473100000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 new file mode 100755 index 0000000..0b0220b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 @@ -0,0 +1,3 @@ +# C-motech CDU-685a +TargetClass=0xff +MessageContent="555342431234567824000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a new file mode 100755 index 0000000..f0375c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a @@ -0,0 +1,3 @@ +# C-motech CHU-629S +TargetClass=0xff +MessageContent="55534243123456782400000080000dfe524445564348473d4e444953000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b new file mode 100755 index 0000000..b006d06 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b @@ -0,0 +1,3 @@ +# C-motech CHU-629S (Variant) +TargetClass=0xff +MessageContent="55534243123456782400000080000dfe524445564348473d4e444953000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 new file mode 100755 index 0000000..540292f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 @@ -0,0 +1,4 @@ +# C-motech CGU-628 (aka "Franklin Wireless CGU-628A" aka "4G Systems XS Stick W12") +TargetVendor=0x16d8 +TargetProduct=0x6006 +MessageContent="55534243d85dd88524000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 new file mode 100755 index 0000000..fd8acfd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 @@ -0,0 +1,4 @@ +# Axesstel MV210 +TargetVendor=0x1726 +TargetProduct=0x1000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e new file mode 100755 index 0000000..abdbe53 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e @@ -0,0 +1,4 @@ +# Axesstel MU130 +TargetVendor=0x1726 +TargetProduct=0xa000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 new file mode 100755 index 0000000..22556bd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 @@ -0,0 +1,2 @@ +# Spreadtrum SC7702 +Configuration=2 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 new file mode 100755 index 0000000..e5f0e4a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 @@ -0,0 +1,2 @@ +# Spreadtrum SC7702 (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 new file mode 100755 index 0000000..2a88764 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 @@ -0,0 +1,4 @@ +# JOA Telecom LM-700r +TargetVendor=0x198a +TargetProduct=0x0002 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd new file mode 100755 index 0000000..20e6c85 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd @@ -0,0 +1,6 @@ +# Beceem BCSM250 +TargetVendor=0x198f +TargetProduct=0x0220 +MessageContent="55534243f0298d8124000000800006bc626563240000000000000000000000" + + diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" new file mode 100755 index 0000000..ec66b7d --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" @@ -0,0 +1,7 @@ +# ZTE generic for Linux (fall-back for unknown products) + +# Uncomment the following lines to activate + +#TargetVendor= 0x19d2 +#StandardEject=1 +#MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 new file mode 100755 index 0000000..1e1f24a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 @@ -0,0 +1,3 @@ +# ZTE MU351 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 new file mode 100755 index 0000000..3d90363 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 @@ -0,0 +1,4 @@ +# ZTE AC581 +TargetVendor=0x19d2 +TargetProductList="0073,0094,0152" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 new file mode 100755 index 0000000..6600b33 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K2525 +TargetVendor=0x19d2 +TargetProduct=0x0022 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 new file mode 100755 index 0000000..8c19d56 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 @@ -0,0 +1,4 @@ +# ZTE MF110 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0031 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA new file mode 100755 index 0000000..3ce0285 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA @@ -0,0 +1,4 @@ +# ZTE MF110 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 new file mode 100755 index 0000000..4c078d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K4505-Z +TargetVendor=0x19d2 +TargetProduct=0x0104 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 new file mode 100755 index 0000000..214f5c0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 @@ -0,0 +1,4 @@ +# ZTE MF112 +TargetVendor=0x19d2 +TargetProduct=0x0031 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 new file mode 100755 index 0000000..e929a64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 @@ -0,0 +1,5 @@ +# ZTE MF637 (Variant for Orange France) +TargetVendor=0x19d2 +TargetProduct=0x0121 +StandardEject=1 + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 new file mode 100755 index 0000000..ae1468e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 @@ -0,0 +1,4 @@ +# ZTE MF651 +TargetVendor=0x19d2 +TargetProduct=0x0116 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 new file mode 100755 index 0000000..5003cfc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 @@ -0,0 +1,7 @@ +#ZTE-T A356 +TargetVendor=0x19d2 +TargetProduct=0x0079 +DetachStorageOnly=0 +StandardEject=1 +Interface=0x00 +NeedResponse=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 new file mode 100755 index 0000000..d7e8196 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 @@ -0,0 +1,4 @@ +# ZTE MF652 (Variant) +TargetVendor=0x19d2 +TargetProductList="0142,0143" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 new file mode 100755 index 0000000..0b06b0f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 @@ -0,0 +1,5 @@ +# ZTE MF190 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 new file mode 100755 index 0000000..0b7cd3b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 @@ -0,0 +1,4 @@ +# ZTE MF656A, MF668A, MF669 +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 new file mode 100755 index 0000000..7fb3c05 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 @@ -0,0 +1,4 @@ +# ZTE MF190 (Variant) and others +TargetVendor=0x19d2 +TargetProductList="0017,0117,2003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 new file mode 100755 index 0000000..8e4414f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 @@ -0,0 +1,4 @@ +# ZTE MF820 4G LTE +TargetVendor=0x19d2 +TargetProduct=0x0167 +MessageContent="55534243123456782400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 new file mode 100755 index 0000000..4aac36c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 @@ -0,0 +1,4 @@ +# ZTE A371B +TargetVendor=0x19d2 +TargetProduct=0x0170 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 new file mode 100755 index 0000000..c12e299 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 @@ -0,0 +1,4 @@ +# ZTE MF820s, MF832s +TargetVendor=0x19d2 +TargetProduct=0x0199 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 new file mode 100755 index 0000000..ed2082f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 @@ -0,0 +1,5 @@ +# Onda MT8205 LTE +TargetVendor=0x19d2 +TargetProduct=0x0265 +StandardEject=1 +MessageContent="55534243d8a523862400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 new file mode 100755 index 0000000..f93dccd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 @@ -0,0 +1,4 @@ +# ZTE MF821D (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0349 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 new file mode 100755 index 0000000..c5bb6e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 @@ -0,0 +1,4 @@ +# ZTE MF821D/MF826 +TargetVendor=0x19d2 +TargetProductList="0317,0330" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 new file mode 100755 index 0000000..3c23ebd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 @@ -0,0 +1,4 @@ +# ZTE MF821D +TargetVendor=0x19d2 +TargetProduct=0x0326 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 new file mode 100755 index 0000000..f7a6966 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 @@ -0,0 +1,4 @@ +# ZTE MF90 Mobile Hotspot +TargetVendor=0x19d2 +TargetProduct=0x0447 +MessageContent="55534243123456782400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 new file mode 100755 index 0000000..3cf0cca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 @@ -0,0 +1,4 @@ +# Telewell TW-LTE 4G +TargetVendor=0x19d2 +TargetProduct=0x0412 +MessageContent="55534243d8a523862400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 new file mode 100755 index 0000000..2d66c17 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3805-Z +TargetVendor=0x19d2 +TargetProductList="1002,1003" +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 new file mode 100755 index 0000000..61a7f71 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K3570-Z +TargetVendor=0x19d2 +TargetProduct=0x1008 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 new file mode 100755 index 0000000..878fcdd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K3571-Z +TargetVendor=0x19d2 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 new file mode 100755 index 0000000..58f33cb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3806-Z +TargetVendor=0x19d2 +TargetProduct=0x1015 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 new file mode 100755 index 0000000..667e00a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 @@ -0,0 +1,4 @@ +# Vodafone K5006Z (MF821) +TargetVendor=0x19d2 +TargetProduct=0x1018 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 new file mode 100755 index 0000000..ef133ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R203 Router +TargetVendor=0x19d2 +TargetProduct=0x1021 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 new file mode 100755 index 0000000..ef133ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R203 Router +TargetVendor=0x19d2 +TargetProduct=0x1021 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 new file mode 100755 index 0000000..de52f8c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 @@ -0,0 +1,4 @@ +# Vodafone / ZTE K4201-z +TargetVendor=0x19d2 +TargetProductList="1023,1024" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 new file mode 100755 index 0000000..a6762cc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R212 Router +TargetVendor=0x19d2 +TargetProductList="1027,1028,1029" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 new file mode 100755 index 0000000..a00acd1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 @@ -0,0 +1,4 @@ +# Vodafone K5008-z (MF823) +TargetVendor=0x19d2 +TargetProductList="1031,1032" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 new file mode 100755 index 0000000..03372d1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R206-z Router +TargetVendor=0x19d2 +TargetProductList="1035,1036,1037" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 new file mode 100755 index 0000000..aac2900 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 @@ -0,0 +1,4 @@ +# ZTE / Vodafone K4607-Z +TargetVendor=0x19d2 +TargetProductList="1039,1040" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 new file mode 100755 index 0000000..878b3fc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R209-z Router +TargetVendor=0x19d2 +TargetProduct=0x1043 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 new file mode 100755 index 0000000..ebf0d0e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 @@ -0,0 +1,4 @@ +# ZTE MF730 +TargetVendor=0x19d2 +TargetProduct=0x1047 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 new file mode 100755 index 0000000..4c722c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K4510-Z +TargetVendor=0x19d2 +TargetProduct=0x1173 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 new file mode 100755 index 0000000..61ef605 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 @@ -0,0 +1,6 @@ +# Vodafone / ZTE K3770-Z +TargetVendor=0x19d2 +TargetProduct=0x1177 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 new file mode 100755 index 0000000..086ade9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3772-Z +TargetVendor=0x19d2 +TargetProduct=0x1181 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 new file mode 100755 index 0000000..052d473 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 @@ -0,0 +1,4 @@ +# ZTE MF691 (T-Mobile Rocket 2.0) +TargetVendor=0x19d2 +TargetProduct=0x1203 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 new file mode 100755 index 0000000..f7e1e50d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1208 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 new file mode 100755 index 0000000..ef7946c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 @@ -0,0 +1,4 @@ +# ZTE MF195 +TargetVendor=0x19d2 +TargetProduct=0x1211 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 new file mode 100755 index 0000000..2634bc1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1217 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 new file mode 100755 index 0000000..f75da93 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProductList="1220,1222" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 new file mode 100755 index 0000000..baa492f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 @@ -0,0 +1,4 @@ +# ZTE MF190 +TargetVendor=0x19d2 +TargetProduct=0x0082 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 new file mode 100755 index 0000000..90b32f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 @@ -0,0 +1,4 @@ +# ZTE MF668 (Variant), MF70 +TargetVendor=0x19d2 +TargetProduct=0x1405 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 new file mode 100755 index 0000000..3ed950f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 @@ -0,0 +1,4 @@ +# ZTE MF680 +TargetVendor=0x19d2 +TargetProduct=0x1252 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 new file mode 100755 index 0000000..086af2c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProductList="1268,2003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 new file mode 100755 index 0000000..ac2c702 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProduct=0x1270 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 new file mode 100755 index 0000000..5b4def7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 @@ -0,0 +1,4 @@ +# ZTE / Vodafone K4201 +TargetVendor=0x19d2 +TargetProduct=0x0017 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 new file mode 100755 index 0000000..ff575e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 @@ -0,0 +1,4 @@ +# ZTE MF825A +TargetVendor=0x19d2 +TargetProduct=0x0017 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 new file mode 100755 index 0000000..a5d5af4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 @@ -0,0 +1,4 @@ +# ZTE MF730 +TargetVendor=0x19d2 +TargetProduct=0x1405 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 new file mode 100755 index 0000000..469143b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProduct=0x1512 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 new file mode 100755 index 0000000..7f08f33 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1515 +MessageContent="5553424348c4758600000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 new file mode 100755 index 0000000..8a7450e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1519 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 new file mode 100755 index 0000000..06c58c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 @@ -0,0 +1,4 @@ +# ZTE MF652 +TargetVendor=0x19d2 +TargetProduct=0x0142 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 new file mode 100755 index 0000000..2a16858 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 @@ -0,0 +1,4 @@ +# ZTE MF591 TMobile +TargetVendor=0x19d2 +TargetProduct=0x1525 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 new file mode 100755 index 0000000..25e78c0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 @@ -0,0 +1,4 @@ +# ZTE MF196 +TargetVendor=0x19d2 +TargetProduct=0x1527 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 new file mode 100755 index 0000000..b3617a6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 @@ -0,0 +1,4 @@ +# ZTE MF190J +TargetVendor=0x19d2 +TargetProductList="1537,1538" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 new file mode 100755 index 0000000..60b06eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 @@ -0,0 +1,4 @@ +# ZTE MF190J +TargetVendor=0x19d2 +TargetProduct=0x1544 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 new file mode 100755 index 0000000..5b99ce8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 @@ -0,0 +1,4 @@ +# ZTE MF195E +TargetVendor= 0x19d2 +TargetProduct=0x1582 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 new file mode 100755 index 0000000..2cbf979 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 @@ -0,0 +1,5 @@ +# ZTE MF710M Variants +TargetVendor= 0x19d2 +TargetProductList="1589,1591,1592" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 new file mode 100755 index 0000000..13cc530 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 @@ -0,0 +1,5 @@ +# ZTE MF710 (Vietnam) a.o. +TargetVendor= 0x19d2 +TargetProductList="1592,1596,1600" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 new file mode 100755 index 0000000..067173e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 @@ -0,0 +1,5 @@ +# ZTE devices, some Onda devices +TargetVendor= 0x19d2 +TargetProductList="0001,0002,0015,0016,0017,0019,0024,0031,0033,0037,0042,0052,0055,0061,0063,0064,0066,0091,0108,0117,0128,0151,0157,0177,1402,2002,2003" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 new file mode 100755 index 0000000..5d97b1e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 @@ -0,0 +1,4 @@ +# ZTE MF60 +TargetVendor=0x19d2 +TargetProduct=0x1402 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd new file mode 100755 index 0000000..dd47bee --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd @@ -0,0 +1,6 @@ +# ZTE AX226 WiMax +TargetVendor=0x19d2 +TargetProduct=0x0172 +MessageContent="555342431234567824000000800006bc626563240000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde new file mode 100755 index 0000000..1beb1df --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde @@ -0,0 +1,4 @@ +# ZTE AC682 (a.k.a. SmartFren Connex) +TargetVendor=0x19d2 +TargetProduct=0xffdd +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 new file mode 100755 index 0000000..e0b6d26 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 @@ -0,0 +1,4 @@ +# ZTE "ffe" devices 1 (e.g. Cricket A605) +TargetVendor=0x19d2 +TargetProduct=0xffe5 +MessageContent="5553424330f4cf8124000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 new file mode 100755 index 0000000..1fa9350 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 @@ -0,0 +1,4 @@ +# ZTE "ff" devices 1 +TargetVendor=0x19d2 +TargetProductList="ffe4,ffe9,fff1,fffe,ffff" +MessageContent="5553424312345678c00000008000069f030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 new file mode 100755 index 0000000..e894e96 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 @@ -0,0 +1,4 @@ +# ZTE "fff" devices 2 +TargetVendor=0x19d2 +TargetProduct=0xfff1 +MessageContent="5553424312345678c00000008000069f030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 new file mode 100755 index 0000000..3580f54 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 @@ -0,0 +1,6 @@ +# BandRich BandLuxe C100, C120, C170, C270, C3xx, C508 +TargetVendor=0x1a8d +TargetProductList="1002,1007,1009,100d,2006" +StandardEject=1 +ReleaseDelay=4000 +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 new file mode 100755 index 0000000..16d85c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 @@ -0,0 +1,4 @@ +# BandRich BandLuxe C339 +TargetVendor=0x1a8d +TargetProduct=0x2006 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 new file mode 100755 index 0000000..983903a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 @@ -0,0 +1,4 @@ +# Hummer DTM5731, Aircard 901 +TargetVendor=0x1ab7 +TargetProductList="2000,5731" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 new file mode 100755 index 0000000..f357fcc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 @@ -0,0 +1,4 @@ +# EpiValley SEC-7089 (featured by Alegro and Starcomms / iZAP) +TargetVendor=0x1b7d +TargetProduct=0x0001 +MessageContent="555342431234567824000000800008FF05B112AEE102000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f new file mode 100755 index 0000000..c618dce --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f @@ -0,0 +1,4 @@ +# ETCOM E300 +TargetVendor=0x1bbb +TargetProduct=0x000f +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca new file mode 100755 index 0000000..df5753b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca @@ -0,0 +1,3 @@ +# Alcatel OT-X080C +TargetClass=0xff +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f new file mode 100755 index 0000000..97f7a3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f @@ -0,0 +1,4 @@ +# Haier EVDO Rev. A +TargetVendor=0x1bbb +TargetProduct=0x0106 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c new file mode 100755 index 0000000..46e4105 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c @@ -0,0 +1,2 @@ +# Alcatel X602D +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e new file mode 100755 index 0000000..717aa47 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e @@ -0,0 +1,4 @@ +# Yota 4G LTE W8 +TargetVendor=0x1bbb +TargetProduct=0x0195 +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 new file mode 100755 index 0000000..bd30b57 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 @@ -0,0 +1,4 @@ +# Alcatel X200/X200L/X060S/L100V, Archos G9 3G Key +TargetVendor=0x1bbb +TargetProductList="0000,0017,00b7,011e,0191,0195" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 new file mode 100755 index 0000000..d68767d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 @@ -0,0 +1,4 @@ +# Alcatel OT-X220D, L100V +TargetVendor=0x1bbb +TargetProductList="0017,011e,0203" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 new file mode 100755 index 0000000..11262b0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 @@ -0,0 +1,4 @@ +# Alcatel OT X220L +TargetVendor=0x1bbb +TargetProduct=0x0052 +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 new file mode 100755 index 0000000..d43b947 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 @@ -0,0 +1,4 @@ +# Alcatel One Touch X020 +TargetVendor=0x1c9e +TargetProductList="6060,6061" +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 new file mode 100755 index 0000000..77cb169 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 @@ -0,0 +1,5 @@ +# TU930, IVIO IV-2010u +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage new file mode 100755 index 0000000..3d6d53d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage @@ -0,0 +1,3 @@ +# Vibe 3G Modem +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 new file mode 100755 index 0000000..ed42e10 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 @@ -0,0 +1,4 @@ +# Emobile D12LC +TargetVendor=0x1c9e +TargetProduct=0x9104 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 new file mode 100755 index 0000000..d0a1e1d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 @@ -0,0 +1,4 @@ +# MyWave SW006 Sport Phone/Modem Combination +TargetVendor=0x1c9e +TargetProduct=0x9202 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 new file mode 100755 index 0000000..e02d00d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 @@ -0,0 +1,4 @@ +# Emobile D21LC +TargetVendor=0x1c9e +TargetProduct=0x9404 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 new file mode 100755 index 0000000..ef03cd9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 @@ -0,0 +1,3 @@ +# Longcheer SU9800 +TargetClass=0xff +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff new file mode 100755 index 0000000..80a3146 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff @@ -0,0 +1,4 @@ +# Telewell TW-3G HSPA+, FS01BU 3G, SmartBro WM66E +TargetVendor=0x1c9e +TargetProductList="6801,9801,9803" +MessageContent="55534243123456780000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe new file mode 100755 index 0000000..25767f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe @@ -0,0 +1,4 @@ +# XS Stick W100 (Omega) +TargetVendor=0x1c9e +TargetProduct=0x9b01 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 new file mode 100755 index 0000000..f8bbedd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 @@ -0,0 +1,3 @@ +# Prolink PCM100 +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 new file mode 100755 index 0000000..3a03904 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 @@ -0,0 +1,3 @@ +# BSNL Capitel +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 new file mode 100755 index 0000000..e90fd46 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 @@ -0,0 +1,6 @@ +# Explay Slim +TargetVendor=0x1c9e +TargetProduct=0x9e18 +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 new file mode 100755 index 0000000..a5b7a8e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 @@ -0,0 +1,5 @@ +# Longcheer/Longsoon (aka Omega Technology) devices +TargetVendor=0x1c9e +TargetProductList="9000,9603,9605,9607,9900" +MessageContent="555342431234567800000000000001ff000000000000000000000000000000" +WaitBefore=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem new file mode 100755 index 0000000..a645abc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem @@ -0,0 +1,5 @@ +# MobiData MBD-200HU and others +TargetVendor=0x1c9e +TargetProductList="9000,9603,9605,9607,9900,9a00" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" +WaitBefore=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 new file mode 100755 index 0000000..d1d007b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 @@ -0,0 +1,4 @@ +# Micromax MMX400R / 4G Systems XSBOXGO +TargetVendor=0x1c9e +TargetProduct=0xf101 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 new file mode 100755 index 0000000..62675f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 @@ -0,0 +1,4 @@ +# TechFaith BSNL Capitel +TargetVendor=0x1d09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 new file mode 100755 index 0000000..3af3048 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 @@ -0,0 +1,4 @@ +# Aiko 81D +TargetVendor=0x1d09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 new file mode 100755 index 0000000..eb9133c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 @@ -0,0 +1,4 @@ +# TechFaith FlyingLARK46 +TargetVendor=0x1d09 +TargetProduct=0x1026 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 new file mode 100755 index 0000000..8cb08ae --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 @@ -0,0 +1,4 @@ +# Qisda H21 Flying Beetle +TargetVendor=0x1da5 +TargetProduct=0x4512 +QisdaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 new file mode 100755 index 0000000..c137caa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 @@ -0,0 +1,2 @@ +# Wisue W340 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 new file mode 100755 index 0000000..2ad5e61 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 @@ -0,0 +1,5 @@ +# Solomon S3Gm-660 +TargetVendor=0x1dd6 +TargetProduct=0x1002 +MessageContent="55534243123456781200000080000603000000020000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 new file mode 100755 index 0000000..92145ba --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 @@ -0,0 +1,4 @@ +# Philips PicoPix 1020 Projector +TargetVendor=0x21e7 +TargetProduct=0x000e +MessageContent="55534243123456780000000000000cff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 new file mode 100755 index 0000000..04931f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 @@ -0,0 +1,5 @@ +# Option iCON 210, PROLiNK PHS100 + PH300, Hyundai MB-810, A-Link 3GU +TargetVendor=0x1e0e +TargetProductList="9000,9100,9200" +MessageContent="555342431234567800000000000006bd000000020000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 new file mode 100755 index 0000000..db6a46d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 @@ -0,0 +1,4 @@ +# 3GO 3GO11 HSUPA +TargetVendor=0x1e89 +TargetProduct=0x1a20 +MessageContent="5553424312345678800000008000060619181a207000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 new file mode 100755 index 0000000..eb04ecd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 @@ -0,0 +1,2 @@ +# AirPlus MCD-800 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 new file mode 100755 index 0000000..a292e64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 @@ -0,0 +1,5 @@ +# Onda MV815U +TargetVendor=0x1ee8 +TargetProduct=0x0004 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 new file mode 100755 index 0000000..9a9fbaa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 @@ -0,0 +1,4 @@ +# Onda POM1051 +TargetVendor=0x1ee8 +TargetProduct=0x000b +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 new file mode 100755 index 0000000..7b7f881 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 @@ -0,0 +1,5 @@ +# Onda MW833UP +TargetVendor=0x1ee8 +TargetProduct=0x000b +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 new file mode 100755 index 0000000..4fc5320 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 @@ -0,0 +1,5 @@ +# Onda MW833UP + MW835UP +TargetVendor=0x1ee8 +TargetProductList="0011,0012,0014" +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 new file mode 100755 index 0000000..d50cde6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 @@ -0,0 +1,5 @@ +# Onda MO835UP +TargetVendor=0x1ee8 +TargetProduct=0x0017 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 new file mode 100755 index 0000000..251f807 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 @@ -0,0 +1,5 @@ +# Onda MW836UP-K +TargetVendor=0x1ee8 +TargetProductList="003e,003f" +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 new file mode 100755 index 0000000..92b567f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 @@ -0,0 +1,5 @@ +# Onda MDC655 +TargetVendor=0x1ee8 +TargetProduct=0x0044 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 new file mode 100755 index 0000000..a0618ab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 @@ -0,0 +1,4 @@ +# Onda MT655 +TargetVendor=0x1ee8 +TargetProduct=0x0049 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a new file mode 100755 index 0000000..97dd71b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a @@ -0,0 +1,4 @@ +# Onda MDC655 +TargetVendor=0x1ee8 +TargetProduct=0x0049 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f new file mode 100755 index 0000000..e81eb29 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f @@ -0,0 +1,5 @@ +# Onda MDC655 Variant +TargetVendor=0x1ee8 +TargetProduct=0x004e +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 new file mode 100755 index 0000000..8638639 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 @@ -0,0 +1,5 @@ +# Onda MW875UP +TargetVendor=0x1ee8 +TargetProduct=0x0053 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 new file mode 100755 index 0000000..985e4a3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 @@ -0,0 +1,4 @@ +# Onda MSA 14.4 (TIM Brasil) +TargetVendor=0x1ee8 +TargetProduct=0x005f +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 new file mode 100755 index 0000000..b46c775 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 @@ -0,0 +1,4 @@ +# Onda TM201, CM201 +TargetVendor=0x1ee8 +TargetProductList="0064,0065" +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 new file mode 100755 index 0000000..da73ac1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 @@ -0,0 +1,4 @@ +# Onda WM301 +TargetVendor=0x1ee8 +TargetProduct=0x0069 +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 new file mode 100755 index 0000000..162c20b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 @@ -0,0 +1,4 @@ +# Cricket A600 +TargetVendor=0x1f28 +TargetProduct=0x0020 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 new file mode 100755 index 0000000..2eabd0a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 @@ -0,0 +1,2 @@ +# Franklin Wireless U210 (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 new file mode 100755 index 0000000..100ce55 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 @@ -0,0 +1,4 @@ +# Franklin Wireless U210 +TargetVendor=0x1fac +TargetProduct=0x0131 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 new file mode 100755 index 0000000..e04b132 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 @@ -0,0 +1,4 @@ +# Franklin Wireless U600 +TargetVendor=0x1fac +TargetProduct=0x0151 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 new file mode 100755 index 0000000..9db4de7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 @@ -0,0 +1,2 @@ +# Franklin Wireless U600 +Configuration=2 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 new file mode 100755 index 0000000..6362dad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 @@ -0,0 +1,4 @@ +# D-Link DWM-157 B1 +TargetVendor=0x2001 +TargetProduct=0x7d02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 new file mode 100755 index 0000000..b1fe1f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 @@ -0,0 +1,2 @@ +# D-Link DWM-157 C1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff new file mode 100755 index 0000000..383e0c7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff @@ -0,0 +1,5 @@ +# D-Link DWM-221 +TargetVendor=0x2001 +TargetProduct=0x7e16 +MessageContent="55534243f8d2e6838000000080000606f50402527000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 new file mode 100755 index 0000000..8d4e874 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 @@ -0,0 +1,4 @@ +# D-Link DWM-221 B1 +TargetVendor=0x2001 +TargetProduct=0x7e19 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 new file mode 100755 index 0000000..d6c4893 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 @@ -0,0 +1,4 @@ +# D-Link DWM-156 A8, DWP-157 B1 +TargetVendor=0x2001 +TargetProductList="7d0b,7d0c" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 new file mode 100755 index 0000000..3208b3b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 @@ -0,0 +1,4 @@ +# D-Link DWM-167 A1 +TargetVendor=0x2001 +TargetProduct=0x7d0d +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 new file mode 100755 index 0000000..4148807 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 @@ -0,0 +1,4 @@ +# D-Link DWM-221 +TargetVendor=0x2001 +TargetProduct=0x7e19 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 new file mode 100755 index 0000000..6522888 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 @@ -0,0 +1,4 @@ +# D-Link DWM-157 C1 +TargetVendor=0x2001 +TargetProduct=0x7d0e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a new file mode 100755 index 0000000..3db2e55 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a @@ -0,0 +1,4 @@ +# D-Link DWM-156 A8 (Myanmar) +TargetVendor=0x2001 +TargetProduct=0x7d10 +MessageContent="555342431234567800000000000003f0010100000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d new file mode 100755 index 0000000..4f12646 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d @@ -0,0 +1,4 @@ +# D-Link DWR-910 +TargetVendor=0x2001 +TargetProduct=0x7e38 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 new file mode 100755 index 0000000..1b4ee3e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 @@ -0,0 +1,4 @@ +# D-Link DWM-156 A7 +TargetVendor=0x2001 +TargetProduct=0x7d01 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 new file mode 100755 index 0000000..6362dad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 @@ -0,0 +1,4 @@ +# D-Link DWM-157 B1 +TargetVendor=0x2001 +TargetProduct=0x7d02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 new file mode 100755 index 0000000..15c8323 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 @@ -0,0 +1,4 @@ +# D-Link DWM-158 D1 +TargetVendor=0x2001 +TargetProduct=0x7d03 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 new file mode 100755 index 0000000..97e0c7b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 @@ -0,0 +1,4 @@ +# D-Link DWR-510 +TargetVendor=0x2001 +TargetProduct=0x7e12 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b new file mode 100755 index 0000000..fbbb6c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b @@ -0,0 +1,5 @@ +# D-Link DWM-156 (Variant) +TargetVendor=0x2001 +TargetProduct=0x7d00 +MessageContent="555342431234567800000000000003f0010100000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 new file mode 100755 index 0000000..02a559f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 @@ -0,0 +1,3 @@ +# Venus VT-18 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 new file mode 100755 index 0000000..98fe5a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 @@ -0,0 +1,6 @@ +# Haier CE682 (EVDO) +TargetVendor=0x201e +TargetProduct=0x1022 +MessageContent="55534243123456780000000000000600000000000000000000000000000000" +MessageContent2="5553424312345679c000000080000671030000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 new file mode 100755 index 0000000..84fefe1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 @@ -0,0 +1,3 @@ +# Haier CE 100 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 new file mode 100755 index 0000000..f67f7a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 @@ -0,0 +1,4 @@ +# Mediatek MT6229, Micromax MMX 377G, Olicard 300 +TargetVendor=0x2020 +TargetProductList="2000,4000,4010" +MessageContent="555342430820298900000000000003f0010100000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e new file mode 100755 index 0000000..ec38550 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e @@ -0,0 +1,5 @@ +# SpeedUp SU-8000 and others +TargetVendor=0x2020 +TargetProductList="1005,1008" +StandardEject=1 +WaitBefore=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f new file mode 100755 index 0000000..64e60f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f @@ -0,0 +1,5 @@ +# SpeedUp SU-8000U +TargetVendor=0x2020 +TargetProduct=0x1005 +StandardEject=1 +WaitBefore=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 new file mode 100755 index 0000000..8bac36b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 @@ -0,0 +1,4 @@ +# Changhong CH690, D-Link DWM-163 + DWM-168 +TargetVendor=0x2077 +TargetProductList="7001,7010,7011" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 new file mode 100755 index 0000000..e65c97b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 @@ -0,0 +1,5 @@ +# Telenet 3G dongle (T&W WU160), Netgear AC327U and others +TargetVendor=0x2077 +TargetProductList="9000,9062,a000,a003" +StandardEject=1 +MessageContent="55534243123456700000000000000616aa0000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a new file mode 100755 index 0000000..9e20b7e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a @@ -0,0 +1,4 @@ +# BM WM78 +TargetVendor=0x20a6 +TargetProduct=0x1000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e new file mode 100755 index 0000000..dd6aefa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e @@ -0,0 +1,4 @@ +# Intex 3.5G +TargetVendor=0x20a6 +TargetProduct=0x1105 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 new file mode 100755 index 0000000..a65c1ea --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 @@ -0,0 +1,3 @@ +# Tlaytech TEU800 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 new file mode 100755 index 0000000..ebb13da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 @@ -0,0 +1,4 @@ +# StrongRising (China Telcom), Air FlexiNet +TargetVendor=0x21f5 +TargetProduct=0x2008 +MessageContent="5553424312345678c000000080000671010000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 new file mode 100755 index 0000000..ef2c097 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 @@ -0,0 +1,4 @@ +# StrongRising STD808 +TargetVendor=0x21f5 +TargetProduct=0x1101 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 new file mode 100755 index 0000000..4339910 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 @@ -0,0 +1,4 @@ +# Viettel VT100 +TargetVendor=0x2262 +TargetProduct=0x0002 +MessageContent="5553424340799288C000000080010A16000000C00000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 new file mode 100755 index 0000000..a610b60 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 @@ -0,0 +1,3 @@ +# WeTelecom WM-D200 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 new file mode 100755 index 0000000..55b59c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 @@ -0,0 +1,4 @@ +# WeTelecom WM-D300 +TargetVendor=0x22de +TargetProduct=0x6801 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 new file mode 100755 index 0000000..7980f66 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 @@ -0,0 +1,3 @@ +# Tata Photon+, Olive VME102 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 new file mode 100755 index 0000000..5008f5c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 (BSNL Teracom) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 new file mode 100755 index 0000000..5008f5c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 (BSNL Teracom) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 new file mode 100755 index 0000000..63996da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 @@ -0,0 +1,2 @@ +# Visiontek 82GH 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b new file mode 100755 index 0000000..e8dd4bb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b @@ -0,0 +1,2 @@ +# Zoom 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c new file mode 100755 index 0000000..e8dd4bb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c @@ -0,0 +1,2 @@ +# Zoom 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d new file mode 100755 index 0000000..66ec4cc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d @@ -0,0 +1,2 @@ +# Intex Speed 3G v7.2 +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 new file mode 100755 index 0000000..721e5c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 new file mode 100755 index 0000000..e543736 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 @@ -0,0 +1,2 @@ +# Teracom LW272 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 new file mode 100755 index 0000000..6251747 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 @@ -0,0 +1,4 @@ +# TP-Link MA180 +TargetVendor=0x2357 +TargetProduct=0x0201 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 new file mode 100755 index 0000000..aba6b49 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 @@ -0,0 +1,4 @@ +# TP-Link MA260 +TargetVendor=0x2357 +TargetProduct=0x9000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 new file mode 100755 index 0000000..95cee31 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 @@ -0,0 +1,4 @@ +# Titan 3.5G +TargetVendor=0x23a2 +TargetProduct=0x1234 +MessageContent="555342431234567800000000000006161f6d62706b00000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 new file mode 100755 index 0000000..e9d346f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 @@ -0,0 +1,4 @@ +# BlueLink BL-EV08C +TargetVendor=0x05c6 +TargetProduct=0x6000 +MessageContent="5553424312345678c000000080000671010000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 new file mode 100755 index 0000000..85b2776 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 @@ -0,0 +1,4 @@ +# Exiss Mobile E-190 series (made by C-motech) +TargetVendor=0x16d8 +TargetProduct=0x6533 +MessageContent="5553424398e2c4812400000080000bff524445564348473d43440000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 new file mode 100755 index 0000000..d23a846 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 @@ -0,0 +1,4 @@ +# Aiko 81D, fw with wrong vendor ID +TargetVendor=0xed09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.h new file mode 100755 index 0000000..f40796f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.h @@ -0,0 +1,116 @@ +/* + This file is part of usb_modeswitch, a mode switching tool for controlling + the mode of 'multi-state' USB devices + + Version 2.4.0, 2016/06/12 + Copyright (C) 2007 - 2016 Josua Dietze + + Config file parsing stuff borrowed from Guillaume Dargaud + (http://www.gdargaud.net/Hack/SourceCode.html) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details: + + http://www.gnu.org/licenses/gpl.txt + +*/ + +#include <stdlib.h> +#include <libusb.h> + +void readConfigFile(const char *configFilename); +void printConfig(); +int switchSendMessage(); +int switchConfiguration(); +int switchAltSetting(); +void switchHuaweiMode(); + +void switchSierraMode(); +void switchGCTMode(); +void switchKobilMode(); +void switchQisdaMode(); +void switchQuantaMode(); +void switchSequansMode(); +void switchActionMode(); +void switchBlackberryMode(); +void switchPantechMode(); +void switchCiscoMode(); +int switchSonyMode(); +int detachDriver(); +int checkSuccess(); +int sendMessage(char* message, int count); +int write_bulk(int endpoint, unsigned char *message, int length); +int read_bulk(int endpoint, unsigned char *buffer, int length); +void release_usb_device(int dummy); +struct libusb_device* search_devices( int *numFound, int vendor, char* productList, + int targetClass, int configuration, int mode); +int find_first_bulk_endpoint(int direction); +int get_current_config_value(); +int get_interface_class(); +char* ReadParseParam(const char* FileName, char *VariableName); +int hex2num(char c); +int hex2byte(const char *hex); +int hexstr2bin(const char *hex, unsigned char *buffer, int len); +void printVersion(); +void printHelp(); +void close_all(); +void abortExit(); +int readArguments(int argc, char **argv); +void deviceDescription(); +void resetUSB(); +void release_usb_device(int dummy); +int findMBIMConfig(int vendor, int product, int mode); + + +// Boolean +#define and && +#define or || +#define not ! + +// Bitwise +#define bitand & +#define bitor | +#define compl ~ +#define xor ^ + +// Equals +#define and_eq &= +#define not_eq != +#define or_eq |= +#define xor_eq ^= + +extern char* ReadParseParam(const char* FileName, char *VariableName); + +extern char *TempPP; + +#define ParseParamString(ParamFileName, Str) \ + if ((TempPP=ReadParseParam((ParamFileName), #Str))!=NULL) \ + strcpy(Str, TempPP); else Str[0]='\0' + +#define ParseParamInt(ParamFileName, Int) \ + if ((TempPP=ReadParseParam((ParamFileName), #Int))!=NULL) \ + Int=atoi(TempPP) + +#define ParseParamHex(ParamFileName, Int) \ + if ((TempPP=ReadParseParam((ParamFileName), #Int))!=NULL) \ + Int=strtol(TempPP, NULL, 16) + +#define ParseParamFloat(ParamFileName, Flt) \ + if ((TempPP=ReadParseParam((ParamFileName), #Flt))!=NULL) \ + Flt=atof(TempPP) + +#define ParseParamBool(ParamFileName, B) \ + if ((TempPP=ReadParseParam((ParamFileName), #B))!=NULL) \ + B=(toupper(TempPP[0])=='Y' || toupper(TempPP[0])=='T'|| TempPP[0]=='1'); else B=0 + +#define ParseParamBoolMap(ParamFileName, B, M, Const) \ + if ((TempPP=ReadParseParam((ParamFileName), #B))!=NULL) \ + if (toupper(TempPP[0])=='Y' || toupper(TempPP[0])=='T'|| TempPP[0]=='1') \ + M=M+Const diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh new file mode 100755 index 0000000..b126ec3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# part of usb_modeswitch 2.4.0 +device_in() +{ + if [ ! -e /var/lib/usb_modeswitch/$1 ]; then + return 0 + fi + while read line + do + if [ $(expr "$line" : "$2:$3") != 0 ]; then + return 1 + fi + done </var/lib/usb_modeswitch/$1 + if [ $(expr "$line" : "$2:$3") != 0 ]; then + return 1 + fi + return 0 +} + +if [ $(expr "$1" : "--.*") ]; then + p_id=$4 + if [ -z $p_id ]; then + prod=$5 + if [ -z $prod ]; then + prod=$3 + fi + prod=${prod%/*} + v_id=0x${prod%/*} + p_id=0x${prod#*/} + if [ "$v_id" = "0x" ]; then + v_id="0" + p_id="0" + fi + v_id="$(printf %04x $(($v_id)))" + p_id="$(printf %04x $(($p_id)))" + else + v_id=$3 + fi +fi +PATH=/sbin:/usr/sbin:$PATH +case "$1" in + --driver-bind) + # driver binding code removed + exit 0 + ;; + --symlink-name) + device_in "link_list" $v_id $p_id + if [ "$?" = "1" ]; then + if [ -e "/usr/sbin/usb_modeswitch_dispatcher" ]; then + exec usb_modeswitch_dispatcher $1 $2 2>>/dev/null + fi + fi + exit 0 + ;; +esac + +IFS='/' read -r p1 p2 <<EOF +$1 +EOF + +PATH=/bin:/sbin:/usr/bin:/usr/sbin +init_path=`readlink /sbin/init` +if [ `basename $init_path` = "systemd" ]; then + systemctl --no-block start usb_modeswitch@$p1'_'$p2.service +elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then + initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1 +else + # only old distros, new udev will kill all subprocesses + exec 1<&- 2<&- 5<&- 7<&- + exec usb_modeswitch_dispatcher --switch-mode $1 & +fi +exit 0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl new file mode 100755 index 0000000..3e590fd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl @@ -0,0 +1,1015 @@ +#!/usr/bin/tclsh + +# Wrapper (tcl) for usb_modeswitch, called from +# /lib/udev/rules.d/40-usb_modeswitch.rules +# (part of data pack "usb-modeswitch-data") via +# /lib/udev/usb_modeswitch +# +# Does ID check on newly discovered USB devices and calls +# the mode switching program with the matching parameter +# file from /usr/share/usb_modeswitch +# +# Part of usb-modeswitch-2.4.0 package +# (C) Josua Dietze 2009-2016 + +set arg0 [lindex $argv 0] +if [regexp {\.tcl$} $arg0] { + if [file exists $arg0] { + set argv [lrange $argv 1 end] + source $arg0 + exit + } +} + +# Setting of these switches is done in the global config +# file (/etc/usb_modeswitch.conf) if available + +set flags(logging) 1 +set flags(noswitching) 0 +set flags(stordelay) 0 +set flags(logwrite) 0 +# also settable in device config files +set flags(nombim) 0 + +# Execution starts at file bottom + +proc {Main} {argv argc} { + +global scsi usb config match device flags setup devdir loginit + +set flags(config) "" +Log "[ParseGlobalConfig]" + +# The facility to add a symbolic link pointing to the +# ttyUSB port which provides interrupt transfer, i.e. +# the port to connect through. +# Will check for interrupt endpoint in ttyUSB port (lowest if +# there is more than one); if found, return "gsmmodem[n]" name +# to udev for symlink creation + +# This is run once for every port of LISTED devices by +# a udev rule + +if {[lindex $argv 0] == "--symlink-name"} { + puts -nonewline [SymLinkName [lindex $argv 1]] + SafeExit +} + +if {[lindex $argv 0] == "--switch-systemd"} { + set argList [split [lindex $argv 1] _] + Log "\nStarted via systemd" +} else { + if {[lindex $argv 0] == "--switch-upstart"} { + Log "\nStarted via upstart" + } + set argList [split [lindex $argv 1] /] +} +if [string length [lindex $argList 1]] { + set device [lindex $argList 1] +} else { + set device "noname" +} +if {$flags(stordelay) > 0} { + SetStorageDelay $flags(stordelay) +} + +Log "Raw args from udev: [lindex $argv 1]\n" + +if {$device == "noname"} { + Log "\nNo data from udev. Exit" + SafeExit +} + +if {![regexp -- {--switch-} [lindex $argv 0]]} { + Log "\nNo command given. Exit" + SafeExit +} + +set setup(dbdir) /usr/share/usb_modeswitch +set setup(dbdir_etc) /etc/usb_modeswitch.d + + +if {![file exists $setup(dbdir)] && ![file exists $setup(dbdir_etc)]} { + Log "\nError: no config database found in /usr/share or /etc. Exit" + SafeExit +} +set bindir /usr/sbin + +set devList1 {} +set devList2 {} + + +# arg 0: the bus id for the device (udev: %b), often ommitted +# arg 1: the "kernel name" for the device (udev: %k) +# +# Used to determine the top directory for the device in sysfs + +set ifChk 0 +if {[string length [lindex $argList 0]] == 0} { + if {[string length [lindex $argList 1]] == 0} { + Log "No device number values given from udev! Exit" + SafeExit + } else { + if {![regexp {(.*?):} [lindex $argList 1] d dev_top]} { + if {![regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top]} { + Log "Could not determine device dir from udev values! Exit" + SafeExit + } + } + } +} else { + set dev_top [lindex $argList 0] + regexp {(.*?):} $dev_top d dev_top +} + +set devdir /sys/bus/usb/devices/$dev_top +if {![file isdirectory $devdir]} { + Log "Top device directory not found ($devdir)! Exit" + SafeExit +} +Log "Use top device dir $devdir" + +set iface 0 +Log "Check class of first interface ..." +set config(class) [IfClass 0 $devdir] +if {$config(class) < 0} { + Log " No access to interface 0. Exit" + SafeExit +} +Log " Interface 0 class is $config(class)." + +set ifdir [file tail [IfDir $iface $devdir]] +regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface + +set flags(logwrite) 1 + +# Mapping of the short string identifiers (in the config +# file names) to the long name used here +# +# If we need them it's a snap to add new attributes here! + +set match(sVe) scsi(vendor) +set match(sMo) scsi(model) +set match(sRe) scsi(rev) +set match(uMa) usb(manufacturer) +set match(uPr) usb(product) +set match(uSe) usb(serial) + + +# Now reading the USB attributes +if {![ReadUSBAttrs $devdir]} { + Log "USB attributes not found in sysfs tree. Exit" + SafeExit +} +set config(vendor) $usb(idVendor) +set config(product) $usb(idProduct) + + +if $flags(logging) { + Log "\n----------------\nUSB values from sysfs:" + foreach attr {manufacturer product serial} { + Log " $attr\t$usb($attr)" + } + Log "----------------" +} + +if $flags(noswitching) { + SysLog "usb_modeswitch: switching disabled, no action for $usb(idVendor):$usb(idProduct)" + Log "\nSwitching globally disabled. Exit" + SafeExit +} + +if {$usb(bNumConfigurations) == "1"} { + set configParam "-u -1" + Log "bNumConfigurations is 1 - don't check for active configuration" +} else { + set configParam "" +} + +# Check (and switch) for operating system if Huawei device present + +set flags(os) "linux" +if {$usb(idVendor) == "12d1" && [regexp -nocase {android} [exec cat /proc/version]]} { + set flags(os) "android" +} +if {$flags(os) == "android"} { + set configList [ConfigGet conflist $usb(idVendor):#android] +} else { + set configList [ConfigGet conflist $usb(idVendor):$usb(idProduct)] +} + +if {[llength $configList] == 0} { + Log "Aargh! Config file missing for $usb(idVendor):$usb(idProduct)! Exit" + SafeExit +} +Log "ConfigList: $configList" + +# Check if there is more than one config file for this USB ID, +# which would make an attribute test necessary. If so, check if +# SCSI values are needed + +set scsiNeeded 0 +if {[llength $configList] > 1} { + if [regexp {:s} $configList] { + set scsiNeeded 1 + } +} +if $scsiNeeded { + if [ReadSCSIAttrs $devdir:$iface] { + Log "----------------\nSCSI values from sysfs:" + foreach attr {vendor model rev} { + Log " $attr\t$scsi($attr)" + } + Log "----------------" + } else { + Log "Could not get SCSI attributes, exclude devices with SCSI match" + } +} else { + Log "SCSI attributes not needed, move on" +} + +# General wait - some devices need this +after 500 + +# Now check for a matching config file. Matching is done +# by MatchDevice + +set report {} +foreach mconfig $configList { + + # skipping installer leftovers like "*.rpmnew" + if [regexp {\.(dpkg|rpm)} $mconfig] {continue} + + Log "Check config: $mconfig" + if [MatchDevice $mconfig] { + Log "! matched. Read config data" +# set flags(config) $mconfig + if [string length $usb(busnum)] { + set busParam "-b [string trimleft $usb(busnum) 0]" + set devParam "-g [string trimleft $usb(devnum) 0]" + } else { + set busParam "" + set devParam "" + } + set flags(config) [ConfigGet conffile $mconfig] + ParseDeviceConfig $flags(config) + if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] { + Log "Note: Using generic manufacturer configuration for \"$flags(os)\"" + } + if $flags(nombim) { + set config(NoMBIMCheck) 1 + } + if {$config(WaitBefore) != ""} { + Log "Delay time of $config(WaitBefore) seconds" + append config(WaitBefore) "000" + after $config(WaitBefore) + Log " wait is over, start mode switch" + } + if {$config(NoMBIMCheck)==0 && $usb(bNumConfigurations) > 1} { + Log "Device may have an MBIM configuration, check driver ..." + if [CheckMBIM] { + Log " driver for MBIM devices is available" + Log "Find MBIM configuration number ..." + if [catch {set cfgno [exec /usr/sbin/usb_modeswitch -j -Q $busParam $devParam -v $usb(idVendor) -p $usb(idProduct)]} err] { + Log "Error when trying to find MBIM configuration, switch to legacy modem mode" + } else { + set cfgno [string trim $cfgno] + if {$cfgno > 0} { + set config(Configuration) $cfgno + set flags(config) "Configuration=$cfgno" + } else { + Log " No MBIM configuration found, switch to legacy modem mode" + } + } + } else { + Log " no MBIM driver found, switch to legacy modem mode" + } + } + if [PantechAutoSwitch] { + Log "Waiting for Pantech auto-modeswitch" + set report "ok:busdev" + break + } + if {$config(Configuration) == 0} { + Log "Config file contains dummy method, do nothing. Exit" + SafeExit + } + UnbindDriver $devdir $ifdir + # Now we are actually switching + if $flags(logging) { + Log "Command to be run:\nusb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$flags(config)" + set report [exec /usr/sbin/usb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1] + Log "\nVerbose debug output of usb_modeswitch and libusb follows" + Log "(Note that some USB errors are to be expected in the process)" + Log "--------------------------------" + Log $report + Log "--------------------------------" + Log "(end of usb_modeswitch output)\n" + } else { + set report [exec /usr/sbin/usb_modeswitch -Q -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1] + } + break + } else { + Log "* no match, don't use this config" + } +} + +# Switching is complete; success checking was either +# done by usb_modeswitch and logged via syslog OR bus/dev +# parameter were used; then we do check for success HERE + +if {$config(Configuration) != ""} { + set ifdir [regsub {(\d):\d+\.0} $ifdir "\\1:$config(Configuration).0"] +} + +if [regexp {ok:busdev} $report] { + if [CheckSuccess $devdir] { + Log "Mode switching was successful, found $usb(idVendor):$usb(idProduct) ($usb(manufacturer): $usb(product))" + SysLog "usb_modeswitch: switched to $usb(idVendor):$usb(idProduct) on [format %03d $usb(busnum)]/[format %03d $usb(devnum)]" + } else { + Log "\nTarget config not matching - current values are" + LogAttributes + Log "\nMode switching may have failed. Exit" + SafeExit + } +} else { + if {![file isdirectory $devdir]} { + Log "Device directory in sysfs is gone! Something went wrong, abort" + SafeExit + } + if {![regexp {ok:} $report]} { + Log "\nCore program reported switching failure. Exit" + SafeExit + } + # Give the device another second if it's not fully back yet + if {![file exists $devdir/idProduct]} { + after 1000 + } + ReadUSBAttrs $devdir $ifdir +} + +# driver binding removed !! + +if {[string length "$usb(idVendor)$usb(idProduct)"] < 8} { + if {![regexp {ok:(\w{4}):(\w{4})} $report d usb(idVendor) usb(idProduct)]} { + Log "No target vendor/product ID found or given, can't continue. Abort" + SafeExit + } +} +# wait for drivers to bind +after 500 +if {[llength [glob -nocomplain $devdir/$ifdir/ttyUSB*]] > 0} { + Log "Serial USB driver bound to interface 0\n will try to guess and symlink modem port on next connect" + AddToList link_list $usb(idVendor):$usb(idProduct) +} + +# In newer kernels there is a switch to avoid the use of a device +# reset (e.g. from usb-storage) which would possibly switch back +# a mode-switching device to initial mode +if [regexp {ok:} $report] { + Log "Check for AVOID_RESET_QUIRK kernel attribute" + if [file exists $devdir/avoid_reset_quirk] { + if [catch {exec echo "1" >$devdir/avoid_reset_quirk 2>/dev/null} err] { + Log " Error setting the attribute: $err" + } else { + Log " AVOID_RESET_QUIRK activated" + } + } else { + Log " not present in this kernel" + } +} + +Log "\nAll done, exit\n" +SafeExit + +} +# end of proc {Main} + + +proc {ReadSCSIAttrs} {topdir} { + +global scsi +set counter 0 +set sysdir $topdir +Log "Check storage tree in sysfs ..." +while {$counter < 20} { + Log " loop $counter/20" + if {![file isdirectory $sysdir]} { + # Device is gone. Unplugged? Switched by kernel? + Log " sysfs device tree is gone; abort SCSI value check" + return 0 + } + # Searching the storage/SCSI tree; might take a while + if {[set dirList [glob -nocomplain $topdir/host*]] != ""} { + set sysdir [lindex $dirList 0] + if {[set dirList [glob -nocomplain $sysdir/target*]] != ""} { + set sysdir [lindex $dirList 0] + regexp {.*target(.*)} $sysdir d subdir + if {[set dirList [glob -nocomplain $sysdir/$subdir*]] != ""} { + set sysdir [lindex $dirList 0] + if [file exists $sysdir/vendor] { + Log " Storage tree is ready" + break + } + } + } + } + after 500 + incr counter +} +if {$counter == 20} { + Log "SCSI tree not found; you may want to check if this path/file exists:" + Log "$sysdir/vendor\n" + return 0 +} + +Log "Read SCSI values ..." +foreach attr {vendor model rev} { + if [file exists $sysdir/$attr] { + set rc [open $sysdir/$attr r] + set scsi($attr) [read -nonewline $rc] + close $rc + } else { + set scsi($attr) "" + Log "Warning: SCSI attribute \"$attr\" not found." + } +} +return 1 + +} +# end of proc {ReadSCSIAttrs} + + +proc {ReadUSBAttrs} {dir args} { + +global usb + +set attrList {idVendor idProduct bConfigurationValue manufacturer product serial devnum busnum bNumConfigurations} +set mandatoryList {idVendor idProduct bNumConfigurations} +set result 1 +if {$args != ""} { + lappend attrList "$args/bInterfaceClass" + lappend mandatoryList "$args/bInterfaceClass" +} +foreach attr $attrList { + if [file exists $dir/$attr] { + set rc [open $dir/$attr r] + set usb($attr) [string trim [read -nonewline $rc]] + close $rc + } else { + set usb($attr) "" + if {[lsearch $mandatoryList $attr] > -1} { + set result 0 + } + if {$attr == "serial"} {continue} + Log " Warning: USB attribute \"$attr\" not found" + } +} +return $result + +} +# end of proc {ReadUSBAttrs} + + +proc {MatchDevice} {config} { + +global scsi usb match + +set devinfo [file tail $config] +set infoList [split $devinfo :] +set stringList [lrange $infoList 2 end] +if {[llength $stringList] == 0} {return 1} + +foreach teststring $stringList { + if {$teststring == "?"} {return 0} + set tokenList [split $teststring =] + set id [lindex $tokenList 0] + set matchstring [lindex $tokenList 1] + set blankstring "" + regsub -all {_} $matchstring { } blankstring + Log "match $match($id)" + Log " string1 (exact): $matchstring" + Log " string2 (blanks): $blankstring" + Log " device string: [set $match($id)]" + if {!([string match *$matchstring* [set $match($id)]] || [string match *$blankstring* [set $match($id)]])} { + return 0 + } +} +return 1 + +} +# end of proc {MatchDevice} + + +proc {ParseGlobalConfig} {} { + +global flags +set configFile "" +set places [list /etc/usb_modeswitch.conf /etc/sysconfig/usb_modeswitch /etc/default/usb_modeswitch] +foreach cfg $places { + if [file exists $cfg] { + set configFile $cfg + break + } +} +if {$configFile == ""} {return} + +set rc [open $configFile r] +while {![eof $rc]} { + gets $rc line + if [regexp {^#} [string trim $line]] {continue} + if [regexp {DisableMBIMGlobal\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(nombim) 1 + } else { + set flags(nombim) 0 + } + } + if [regexp {DisableSwitching\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(noswitching) 1 + } + } + if [regexp {EnableLogging\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(logging) 1 + } else { + set flags(logging) 0 + } + } + if [regexp {SetStorageDelay\s*=\s*([^\s]+)} $line d val] { + if [regexp {\d+} $val] { + set flags(stordelay) $val + } + } + +} +return "Use global config file: $configFile" + +} +# end of proc {ParseGlobalConfig} + + +proc ParseDeviceConfig {cfg} { + +global config +set config(WaitBefore) "" +set config(TargetVendor) "" +set config(TargetProduct) "" +set config(TargetClass) "" +set config(Configuration) "" +set config(NoMBIMCheck) 0 +set config(PantechMode) 0 +set config(CheckSuccess) 20 + +foreach pname [lsort [array names config]] { + if [regexp -line "^\[^# \]*?$pname.*?= *(0x(\\w+)|\"(\[0-9a-fA-F,\]+)\"|(\[0-9\]+)) *\$" $cfg d config($pname)] { +# Log "config: $pname set to $config($pname)" + } +} + +set config(WaitBefore) [string trimleft $config(WaitBefore) 0] + +} +# end of proc {ParseDeviceConfig} + + +proc ConfigGet {command config} { + +global setup usb flags + +switch $command { + + conflist { + # Unpackaged configs first; sorting is essential for priority + set configList [lsort -decreasing [glob -nocomplain $setup(dbdir_etc)/$config*]] + set configList [concat $configList [lsort -decreasing [glob -nocomplain $setup(dbdir)/$config*]]] + eval lappend configList [glob -nocomplain $setup(dbdir)/$usb(idVendor):#$flags(os)] + if [file exists $setup(dbdir)/configPack.tar.gz] { + Log "Found packed config collection $setup(dbdir)/configPack.tar.gz" + if [catch {set packedList [exec tar -tzf $setup(dbdir)/configPack.tar.gz 2>/dev/null]} err] { + Log "Error: problem opening config package; tar returned\n $err" + return {} + } + set packedList [split $packedList \n] + set packedConfigList [lsort -decreasing [lsearch -glob -all -inline $packedList $config*]] + lappend packedConfigList [lsearch -inline $packedList $usb(idVendor):#$flags(os)] + # Now add packaged configs with a mark, again sorted for priority + foreach packedConfig $packedConfigList { + lappend configList "pack/$packedConfig" + } + } + return $configList + } + conffile { + if [regexp {^pack/} $config] { + set config [regsub {pack/} $config {}] + Log "Extract config $config from collection $setup(dbdir)/configPack.tar.gz" + set configContent [exec tar -xzOf $setup(dbdir)/configPack.tar.gz $config 2>/dev/null] + } else { + if [regexp [list $setup(dbdir_etc)] $config] { + Log "Use config file from override folder $setup(dbdir_etc)" + SysLog "usb_modeswitch: use overriding config file $config; make sure this is intended" + SysLog "usb_modeswitch: please report any new or corrected settings; otherwise, check for outdated files" + } + set rc [open $config r] + set configContent [read $rc] + close $rc + } + return $configContent + } +} + +} +# end of proc {ConfigGet} + +proc {Log} {msg} { + +global flags device loginit + +if {$flags(logging) == 0} {return} + +if $flags(logwrite) { + if [string length $loginit] { + exec echo "\nUSB_ModeSwitch log from [clock format [clock seconds]]" >/var/log/usb_modeswitch_$device + exec echo "$loginit" >>/var/log/usb_modeswitch_$device + set loginit "" + } + exec echo $msg >>/var/log/usb_modeswitch_$device +} else { + append loginit "\n$msg" +} + +} +# end of proc {Log} + + +# Writing the log file and exit +proc {SafeExit} {} { + +global flags +set flags(logwrite) 1 +Log "" +exit + +} +# end of proc {SafeExit} + + +proc {SymLinkName} {path} { +global device flags + +proc {hasInterrupt} {ifDir} { + if {[llength [glob -nocomplain $ifDir/ttyUSB*]] == 0} { + Log " no ttyUSB interface - skip endpoint check" + return 0 + } + foreach epDir [glob -nocomplain $ifDir/ep_*] { + set e [file tail $epDir] + Log " check $e ..." + if [file exists $epDir/type] { + set rc [open $epDir/type r] + set type [read $rc] + close $rc + if [regexp {Interrupt} $type] { + Log " $e has interrupt transfer type" + return 1 + } + } + } + return 0 +} + +set loginit "usb_modeswitch called with --symlink-name\n parameter: $path\n" + +# In case the device path is returned as /class/tty/ttyUSB, +# get the USB device path from linked tree "device" +set linkpath /sys$path/device +if [file exists $linkpath] { + if {[file type $linkpath] == "link"} { + set rawpath [file readlink $linkpath] + set trimpath [regsub -all {\.\./} $rawpath {}] + if [file isdirectory /sys/$trimpath] { + append loginit "\n Use path $path\n" + set path /$trimpath + } + } +} +if {![regexp {([0-9]+-[0-9]+[\.0-9]*:[^/]*).*(ttyUSB[0-9]+)} $path d myDev myPort]} { + if $flags(logging) { + set device [clock clicks] + set flags(logwrite) 1 + Log "$loginit\nThis is not a ttyUSB port. Abort" + } + return "" +} + +set device ttyUSB_$myDev +set flags(logwrite) 1 +Log "$loginit\nMy name is $myPort\n" + +if {![regexp {(.*?[0-9]+)\.([0-9]+)/ttyUSB} /sys$path d ifRoot ifNum]} { + Log "Could not find interface in path\n $path. Abort" + return "" +} + +set ifDir $ifRoot.$ifNum + +Log "Check my endpoints ...\n in $ifDir" +if [hasInterrupt $ifDir] { + Log "\n--> I am an interrupt port" + set rightPort 1 +} else { + Log "\n--> I am not an interrupt port\n" + set rightPort 0 +} + +# There are devices with more than one interrupt interface. +# Assume that the lowest of these is usable. Check all +# possible lower interfaces + +if { $rightPort && ($ifNum > 0) } { + Log "\nLook for lower ports with interrupt endpoints" + for {set i 0} {$i < $ifNum} {incr i} { + set ifDir $ifRoot.$i + Log " in ifDir $ifDir ..." + if [hasInterrupt $ifDir] { + Log "\n--> found an interrupt interface below me\n" + set rightPort 0 + break + } + } +} +if {$rightPort == 0} { + Log "Return empty name and exit" + return "" +} + +Log "\n--> No interrupt interface below me\n" + +cd /dev +set idx 2 +set symlinkName "gsmmodem" +while {$idx < 256} { + if {![file exists $symlinkName]} { + set placeholder [open /dev/$symlinkName w] + close $placeholder + break + } + set symlinkName gsmmodem$idx + incr idx +} +if {$idx == 256} {return ""} + +Log "Return symlink name \"$symlinkName\" and exit" +return $symlinkName + +} +# end of proc {SymLinkName} + + +# Add USB ID to list of devices needing later treatment +proc {AddToList} {name id} { + +set listfile /var/lib/usb_modeswitch/$name +if [file exists $listfile] { + set rc [open $listfile r] + set buffer [read $rc] + close $rc + if [string match *$id* $buffer] { + return + } + set idList [split [string trim $buffer] \n] +} +lappend idList $id +set buffer [join $idList "\n"] +if [catch {set lc [open $listfile w]}] {return} +puts $lc $buffer +close $lc + +} +# end of proc {AddToList} + + +proc {CheckSuccess} {devdir} { + +global config usb flags + +# For Cisco AM10, target device not on same port +if {$usb(idVendor) == "1307" && $usb(idProduct) == "1169"} { + set devdir [string range $devdir 0 end-1]2 +} +set ifdir [file tail [IfDir 0 $devdir]] +if {[string length $config(TargetClass)] || [string length $config(Configuration)]} { + set config(TargetVendor) $usb(idVendor) + set config(TargetProduct) $usb(idProduct) +} +Log "Check success of mode switch for max. $config(CheckSuccess) seconds ..." + +set expected 1 +for {set i 1} {$i <= $config(CheckSuccess)} {incr i} { + after 1000 + if {![file isdirectory $devdir]} { + Log " Wait for device file system ($i sec.) ..." + continue + } else { + Log " Read attributes ..." + } + set ifdir [IfDir 0 $devdir] + if {$ifdir == ""} {continue} + set ifdir [file tail $ifdir] + if {![ReadUSBAttrs $devdir $ifdir]} { + Log " Essential attributes are missing, continue wait ..." + continue + } + if [string length $config(Configuration)] { + if {$usb(bConfigurationValue) != $config(Configuration)} {continue} + } + if [string length $config(TargetClass)] { + if {![regexp $usb($ifdir/bInterfaceClass) $config(TargetClass)]} { + if {$config(class) != $usb($ifdir/bInterfaceClass} { + set expected 0 + } else {continue} + } + } + if {![regexp $usb(idVendor) $config(TargetVendor)]} { + if {![regexp $usb(idVendor) $config(vendor)]} { + set expected 0 + } else {continue} + } + if {![regexp $usb(idProduct) $config(TargetProduct)]} { + if {![regexp $usb(idProduct) $config(product)]} { + set expected 0 + } else {continue} + } + # Arriving here means that device attributes have changed + if $expected { + Log " All attributes matched" + } else { + if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] { + Log " idProduct has changed after generic mode-switch, assume success" + } else { + Log " Attributes are different but target values are unexpected:" + LogAttributes + } + } + break +} +if {$i > 20} {return 0} else {return 1} + +} +# end of proc {CheckSuccess} + + +proc {IfDir} {iface devdir} { + +set allfiles [glob -nocomplain $devdir/*] +set files [glob -nocomplain $devdir/*.$iface] +if {[llength $files] == 0} { + return "" +} +set ifdir [lindex $files 0] +if {![file isdirectory $ifdir]} { + return "" +} +return $ifdir + +} +# end of proc {IfDir} + +proc {IfClass} {iface devdir} { + +set ifdir [IfDir $iface $devdir] + +if {![file exists $ifdir/bInterfaceClass]} { + return -1 +} +set rc [open $ifdir/bInterfaceClass r] +set c [read $rc] +close $rc +return [string trim $c] + +} +# end of proc {IfClass} + + +proc {SysLog} {msg} { + +global flags +if {![info exists flags(logger)]} { + set flags(logger) "" + foreach fn {/bin/logger /usr/bin/logger} { + if [file exists $fn] { + set flags(logger) $fn + } + } + Log "Logger is $flags(logger)" +} +if {$flags(logger) == ""} { + Log "Can't add system message, no syslog helper found" + return +} +catch {exec $flags(logger) -p syslog.notice "$msg" 2>/dev/null} + +} +# end of proc {SysLog} + +proc {SetStorageDelay} {secs} { + +Log "Adjust delay for USB storage devices ..." +set attrib /sys/module/usb_storage/parameters/delay_use +if {![file exists $attrib]} { + Log "Error: could not find delay_use attribute" + return +} +if [catch {set ch [open $attrib r+]} err] { + Log "Error: could not access delay_use attribute: $err" + return +} +if {[read $ch] < $secs} { + seek $ch 0 start + puts -nonewline $ch $secs + Log " Delay set to $secs seconds\n" +} else { + Log " Current value is higher than $secs. Leave it alone\n" +} +close $ch + +} +# end of proc {SetStorageDelay} + +proc {CheckMBIM} {} { + +set kversion [exec uname -r] +if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/cdc_mbim*]] {return 1} +if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1} +return 0 + +} + +proc {CheckQMI} {} { + +set kversion [exec uname -r] +if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/qmi_wwan*]] {return 1} +if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1} +return 0 + +} + +proc {PantechAutoSwitch} {} { + +global config flags +if {$config(PantechMode) == 3} {return 1} +if {$config(PantechMode) == 1} { + if {"$config(vendor):$config(product)" == "10a9:6080"} { + set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=2"] + Log " PantechMode changed to 2" + return 0 + } elseif [CheckQMI] { + set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=4"] + Log " PantechMode changed to 4" + return 0 + } else { + return 1 + } +} else {return 0} + +} + +proc UnbindDriver {devdir ifdir} { + +set att $devdir/$ifdir/driver/unbind +if [file exists $att] { + Log "Unbinding driver" + exec echo -n "$ifdir" > $att +} + +} + +proc {LogAttributes} {} { + +global flags usb +if $flags(logging) { + set attrList {idVendor idProduct bConfigurationValue manufacturer product serial} + foreach attr [lsort [array names usb]] { + Log " [format %-26s $attr:] $usb($attr)" + } +} + +} + +proc {HasFF} {devdir} { + +set i 0 +while {[set dir [IfDir $i $devdir]] != ""} { + set c [exec cat $dir/bInterfaceClass] + if {$c == "ff"} {return 1} + incr i +} +return 0 + +} + + +# The actual entry point +Main $argv $argc diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Android.mk b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Android.mk new file mode 100755 index 0000000..5dacae0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +INCLUDES = $(LOCAL_PATH) +INCLUDES += external/libusb/libusb + +LOCAL_PROPRIETARY_MODULE := true +LOCAL_MODULE := usb_modeswitch +LOCAL_SRC_FILES := usb_modeswitch.c +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES :=$(INCLUDES) +LOCAL_SHARED_LIBRARIES := libusb + +LOCAL_CFLAGS += -Wno-self-assign -Wno-sometimes-uninitialized +LOCAL_CFLAGS += -Wno-error=deprecated-declarations -Wno-deprecated-declarations + +$(shell mkdir -p $(PRODUCT_OUT)/vendor/etc) +$(shell cp -R $(LOCAL_PATH)/usb_modeswitch.d $(PRODUCT_OUT)/vendor/etc) + +include $(BUILD_EXECUTABLE) + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/COPYING b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/COPYING new file mode 100755 index 0000000..d60c31a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/ChangeLog b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/ChangeLog new file mode 100755 index 0000000..42ee92a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/ChangeLog @@ -0,0 +1,288 @@ + +History of USB_ModeSwitch +========================= + +Version 2.4.0, 2016/06/12 + ATTENTION: All ad-hoc driver binding code (using new_id driver attribute) + removed - was a potential source of side effects and should now be + obsoleted by good kernel support for modems; Added "dummy" setting for + config files, to conditionally refrain from handling a device (see this + topic: www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?f=4&t=2458 ); + extended StandardEject sequence to include LUN 1, required for some D-Link + devices; add device class 239 ("miscellaneous") to sanity check (thanks to + Daniel Drake for reporting); udev shell script - removed driver binding, + removed almost all waiting and forking, improved check for systemd (thanks + to Daniel Drake for problem analysis and solution, see this topic/patch: + www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?p=16777#p16777 , + gist.github.com/dsd/9f83c4830ab78ce94078aedb2cf16a8f ) +Version 2.3.0, 2016/01/12 + ATTENTION: -I flag is now history and being ignored - determining SCSI + attributes is really an 'outside task'; -n flag (NeedResponse) is being + ignored, CSW response will now always be read; introduction of parameter + "OptionMode", wrapping the standard bulk message for all newer Huawei + devices; fixed missing variable initialization in dispatcher script which + could lead to crash (thanks, Dmitry Kunilov!); fixed bug which prevented + early logging; fixed success report for Cisco AM10; some source code + formatting and clean-up +Version 2.2.6, 2015/11/01 + Renamed function abort(), avoiding possible conflicts in static builds + with libjim (thanks, Gustavo Zacharias); removed storage class check of + interface 0 from dispatcher, enabling new multi-config devices in data + package 20151101 +Version 2.2.5, 2015/07/16 + Fixed bug in configuration check, possibly leading to segfault (thanks, + Leonid Lisovskiy); fixed Pantech commandline parameter evaluation (was + not working at all); added driver unbind step via sysfs in wrapper, + getting rid of the USB subsystem complaint "interface 0 claimed by + usb-storage while 'usb_modeswitch' <does this and that>" +Version 2.2.4, 2015/07/14 + Fixed buggy check of USB configuration selection (possibly leading + to segfault), tested with Alcatel X602D; removed call to 'libusb_strerror' + from libusb initialization - not available in earlier libusb1 versions +Version 2.2.3, 2015/06/29 + Fixed problem arising with systemd version 221 (220 untested), which + affects starting the usb_modeswitch systemd unit from the sh script + (reported by Archlinux users) +Version 2.2.2, 2015/06/27 + Added catch for libusb init error (thanks, Henrik Gustafsson); removed + global function result variable; added catch for USB configuration + read error (both thanks to "otila"); fixed wrapper script where port + search for symlinking modem port was broken ("/dev/gsmmodem"); changed + PantechMode parameter to represent different targets; added global + config option to disable MBIM checking and setting alltogether (request + from "kai"); changed udev sh script so that systemd processing takes + precedence over upstart; changed systemd template unit parameter to + avoid escaping problems +Version 2.2.1, 2015/01/15 + Fixed unreliable switching function for Cisco AM10 +Version 2.2.0, 2014/05/29 + Introduction of parameter "HuaweiNewMode", wrapping the standard bulk + message for all newer Huawei devices; support for generic fall-back + config files, combined with OS switch (per vendor ID), implementation + to use a specific switching command on Android for all Huawei devices + (see README of data package for details); this change was suggested + by Huawei +Version 2.1.1, 2014/03/27 + Code cleanup, better use of libusb1; this also fixes problems with + determination of the active USB configuration (Samsung, Option modems); + "Interface" parameter was not working as expected, fixed (see also: + https://bugs.launchpad.net/bugs/1261923 ); fixed bogus interface release + in "inquire" function, again a report by "Sonya@zte" +Version 2.1.0, 2014/01/28 + ATTENTION: -I flag meaning reversed, default is to skip SCSI inquiry; + introduction of StandardEject, replacing many MessageContents with the + same function, reducing size of device config files, and always including + the 'Allow Medium Removal' before ejecting (thanks to Lars Melin for + the idea); fix in "bulk_read", removing bogus CSW request (report from + "Sonya@zte") +Version 2.0.1, 2013/09/03 + Fixed stupid string size bug which could lead to memory corruption + (thanks to Leonid Myravjev) +Version 2.0.0, 2013/09/01 + Switched to libusb1.0, with much help from folks of the wl500g project + (http://wl500g.googlecode.com): Vladislav Grishenko, Leonid Lisovskiy, + Roman Samarev, Andrey Tikhomirov; + major code and debug output cleanup; man page corrections and additions + (thanks to Thomas Haller); + experimental systemd and upstart integration, if present + (Explanation: newer udev versions kill all subprocesses, detached or + not. The suggested way to handle longer running processes like the + usb_modeswitch_dispatcher is to add simple services or tasks and start + these by sending signals from the udev rule) + !! Attention, system integrators: a crude install facility is included + in the Makefile to check if "upstart" or "systemd" is active and to + install the matching service file; you may want to adapt it better to + your respective system, possibly adding dependencies/targets to the + services. Note that the udev starter script usb_modeswitch.sh also + checks for the existence of the service/unit files +Version 1.2.7, 2013/08/07 + Two new dedicated control message functions to support Pantech LTE + (thanks to Adam Goode) and Blackberry Q10/Z10 (thanks to Daniel Mende) +Version 1.2.6, 2013/06/02 + Several changes to streamline compiling as part of larger projects + (thanks to Nicolas Carrier), mostly in Makefile; fix compiler warnings + appearing in certain build environments (N. Carrier); new Quanta + procedure (thanks to Andrey Tikhomirov) for Quanta 1K3 LTE; fix for + error with cascaded hubs in dispatcher script (hint from N. Carrier) +Version 1.2.5, 2012/11/09 + Initial support for MBIM devices, use with data package >= 20121109; + checking for these is the automatic default, new parameter NoMBIMCheck + prevents the check per device in case of problems; new global option + to set "delay_use" of usb-storage (as low values may prevent + mode-switching); fix for handling multi-configuration devices (thanks + to Bjørn Mork for advice) +Version 1.2.4, 2012/08/12 + Additional interface checks to prevent sending UFI commands to non- + storage interfaces (prompted by more ambiguous device IDs popping up); + change in SierraMode for handling newer devices which caused an error + abort before; Makefile fix for parallelized make runs +Version 1.2.3, 2012/01/28 + Fixed two bugs both causing the embedded-jimsh install variant of the + dispatcher crash (the "pure-script" install variant was NOT affected); + fixed some "regexp" incompatibilities with Debian's libjim +Version 1.2.2, 2012/01/19 + Fixed bad bug preventing mode switch for devices using TargetClass; + improved logging in case of negative success check +Version 1.2.1, 2011/12/26 + Fixed possible ambiguities when multiple identical modems are plugged + synchronously; this is achieved by adding -b and -g parameter (busnum + and devnum) for proper id'ing; some resulting workflow changes and + shortcuts in "system integration" mode (use sysfs/wrapper for success + control, reduce informative checks); improved hub usage robustness; + future data packages can be ridded of redundancies (default ID, success + check parameters), resulting in smaller files; + fixed bad bug which may prevent switching completely when logging is + not activated; fixed possible overflow in dispatcher C code (thanks to + Gilles Espinasse) +Version 1.2.0, 2011/10/23 + Added QisdaMode for Qisda H21 (thanks to Chi-Hang Long for the code); + dispatcher can now be installed with an embedded interpreter, so that + Tcl is no longer required; added command line options for binary program + to accept configuration data via stdin or as a long string parameter - + this fixes the bug with non-writable temporary file during boot; + reversed skipping of pre-switching delay, which has caused problems; + fixed potential buffer overflow (thanks to Rafael Silva for the find); + get first interface right even on some broken devices (thanks to + Alexander Gordeev for the patch); increased post-switch delay before + driver binding to avoid possible conflict with usb-storage +Version 1.1.9, 2011/08/05 + Added CiscoMode for Valet device; additional checking for CDC ACM device + to prevent erroneous driver loading after switching; no more post-switch + check for access to initial device if target parameters are given +Version 1.1.8, 2011/06/19 + Cleaned up switchSendMessage(); added workaround for quirky devices not + reporting configuration setting; added non-CSW response for arbitrary + bulk transfers; added SequansMode and MobileActionMode; check for active + configuration will be skipped if bNumConfigurations is 1 (most cases) +Version 1.1.7, 2011/02/27 + Attention: paths for runtime files and database have changed! Old places + will be found but are deprecated; /usr/share/usb_modeswitch for database, + /var/lib/usb_modeswitch for "remembered" IDs; + fix for configuration setting race (thanks to Amit Mendapara); discovered + incompatibility between Tcl versions <= 8.3 and >=8.4, so 8.4 is the + minimum prerequisite now; + first availability of an alternative source pack which includes "jimsh", + a fast Tcl mini shell, intended for resource-constrained systems +Version 1.1.6, 2010/12/22 + Moved warm-boot driver binding to sh wrapper, was unreliable in 1.1.5; + sh wrapper overhaul, made compatible with Ubuntu's "dash" shell, tclsh + calls reduced further; initial device checking includes current + bConfigurationValue now, should work with config setting for multiple + devices; made tcl script conform to limitations of "jimsh", the minimal + tcl shell (hint from Barry Kauler); fixes for "usbserial" fallback + (driver binding for old systems); in the C program, changed parameter + "MessageDelay" (hitherto unused) to "ReleaseDelay", to be used in one + device configuration (delay interface release after bulk message sending) +Version 1.1.5, 2010/11/28 + Added special control message for Kobil devices (patch from Filip Aben); + try to get active configuration for interface class checking (there are + some new devices 'switching' via configuration selection); + fixed "0000" target product ID - again; new bash and tcl wrapper logic: + the convenience functions for driver binding and symlinking will now + start the tcl shell ONLY for known devices; changed and appended logging + capabilities of said convenience functions; add loading of "usbserial" + as a fallback for older systems to support new devices; + add workaround for bug in libusb1 which affects device search during + success check +Version 1.1.4, 2010/08/17 + The package should work at boot time now (cold and warm); + product IDs of "0000" do exist but were not accepted, fixed (thanks to + Sakis Dimopoulos); response endpoint is now always detected (led to + possible error report when resetting all endpoints in version 1.1.3); + wrapper script can now work with a packed collection of config files as + well as with the plain folder of files; use with the "install-packed" + make target of the data package (for use on systems with resource + constraints); wrapper fix for the symlink feature: handling of multiple + interrupt ports was incomplete; wrapper does not longer use a temporary + file for the symlink feature (security considerations, Marco d'Itri) +Version 1.1.3, 2010/06/21 + Added delay option to separate multiple message transfers by millisecs; + fixed (possibly dangerous) sloppy string handling (thanks to Christophe + Fergeau); added "clear_halt" for response endpoint; small additions in + Makefile (install with -D); changes in option handling (NO MORE DEFAULT + CONFIG FILE!) and help text; symlink feature in wrapper can now cope + with devices providing more than one interrupt port; wrapper now ignores + package manager leftovers in config folder; replaced bash-specific syntax + in wrapper; changed ZTE skipping (if existing rules are found) to warning +Version 1.1.2, 2010/04/18 + Added support for two additional bulk messages; wrapper handles special + ZTE case; generalized driver loading, new parameter "DriverModule" and + "DriverIDPath"; new wrapper facility to add symlink pointing to interrupt + port (used in rule file from data pack >= 20100418) +Version 1.1.1, 2010/03/17 + Attention: old usb_modeswitch.conf renamed to usb_modeswitch.setup! + Add separate config file for wrapper (global settings for switching and + logging); add config file option to disable driver loading; handling of + kernel attribute AVOID_RESET_QUIRK added; bug fixed in SonyMode (reported + by "no-0n3"); bug fixed in SuccessCheck logic; minor flow alignments and + fixes; new devices +Version 1.1.0, 2010/01/24 + Attention: wrapper script location changed, uninstall old versions! + Major fixes in the wrapper script (stabilizing and time-saving); + back to unified installation, defaults to "integrated" approach; + new -D parameter to enable "integrated" behaviour; bugs fixed in + success check; man file included (borrowed from the Debian package); + C code and binary works with the compat library from libusb-1.0; + some new devices +Version 1.0.7, 2010/01/06 + Bug fixed for Sony mode, thanks to Marco Chiaranda; fix for parameter + substitution in newer udev versions, fix for bad bug in wrapper script + practically disabling automatic mode +Version 1.0.6, 2009/12/21 + New "GCT Mode", fixes for device quirks (NXP Dragonfly), fix for multiple + Huawei devices, cleanups, loads of new devices in config file and database, + minor tcl script changes +Version 1.0.5, 2009/08/26 + More changes and fixes regarding success check; "--version" option; + config "database" updated +Version 1.0.4, 2009/08/23 + Success check bugs (and others) fixed +Version 1.0.3, 2009/08/20 + Success check improved; experimental system integration (fully automated), + optional; new parameter "TargetProductList" needed for this; other + necessary small adaptations; more devices +Version 1.0.2, 2009/06/10 + Output bugs fixed +Version 1.0.1, 2009/06/08 + Added output of descriptor strings for further identification +Version 1.0.0, 2009/06/01 + Attention: possible incompatibilities for command line control! + On/off flags don't require arguments anymore (-H, -S, -O, -d, -R, + -n, new: -I), meaning "-R 0" does a reset like "-R 1" or "-R"; + long option names changed to standard format (e.g. --HuaweiMode to + --huawei-mode); added device inquiry, for future help with device + identification; catch error -19 as possible success; send and response + endpoints now autoselected (consequently NeedResponse is back); + new devices +Version 0.9.7, 2009/04/15 + Updated SonyMode, MD 400 now stable; automatic default endpoint + detection from Andrew Bird +Version 0.9.7beta, 2009/03/15 + Major code clean up, optional success control (both suggested + by Daniel Cooper), new devices +Version 0.9.6, 2009/01/08 + Special modes added for Sierra and Sony Ericsson, new devices +Version 0.9.5, 2008/10/27 + New options for USB tuning (jokedst), lots of new devices, clean up +Version 0.9.4, 2008/06/09 + Compat fix for libusb on FreeBSD quirks, more devices +Version 0.9.4beta2, 2008/03/19 + Successful udev device release fix +Version 0.9.4beta, 2008/03/16 + Multiple device support +Version 0.9.3, 2008/03/09 + More devices, no changes from beta version +Version 0.9.3beta, 2007/12/30 + New TargetClass parameter for recent Option firmware (Paul Hardwick), more + devices +Version 0.9.2, 2007/11/02 + New Huawei mode (code from Miroslav Bobovsky, added by Denis Sutter), more + devices +Version 0.9.1beta, 2007/09/04 (jokedst) + Added command line parsing, cleaned up config stuff, doc updates +Version 0.9beta, 2007/08/15 + Name change from "icon_switch", parameter file and generalizing +Version 0.2, 2006/09/25 + Code cleaning, more messages +Version 0.1, 2006/09/24 + (as "icon_switch") Just very basic functionality ... diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Makefile b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Makefile new file mode 100755 index 0000000..47ed794 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/Makefile @@ -0,0 +1,105 @@ +PROG = usb_modeswitch +VERS = 2.4.0 +CC ?= gcc +CFLAGS += -Wall +LIBS = `pkg-config --libs --cflags libusb-1.0` +RM = /bin/rm -f +OBJS = usb_modeswitch.c +PREFIX = $(DESTDIR)/usr +ETCDIR = $(DESTDIR)/etc +SYSDIR = $(ETCDIR)/systemd/system +UPSDIR = $(ETCDIR)/init +UDEVDIR = $(DESTDIR)/lib/udev +SBINDIR = $(PREFIX)/sbin +MANDIR = $(PREFIX)/share/man/man1 +VPATH = jimtcl +HOST_TCL := $(shell cd jim && ./autosetup/find-tclsh) +ifeq (,$(findstring jimsh0,$(HOST_TCL))) +TCL ?= $(HOST_TCL) +else +TCL ?= /usr/bin/tclsh +endif +JIM_CONFIGURE_OPTS = --disable-lineedit \ + --with-out-jim-ext="stdlib posix load signal syslog" --prefix=/usr + +.PHONY: clean install install-common uninstall \ + script shared static \ + dispatcher-script dispatcher-shared dispatcher-static \ + install-script install-shared install-static + +all: script + +script: $(PROG) dispatcher-script + +shared: $(PROG) dispatcher-shared + +static: $(PROG) dispatcher-static + +$(PROG): $(OBJS) usb_modeswitch.h + $(CC) -o $(PROG) $(OBJS) $(CFLAGS) $(LIBS) $(LDFLAGS) + +jim/libjim.so: + cd jim && CFLAGS="$(CFLAGS)" CC="$(CC)" ./configure $(JIM_CONFIGURE_OPTS) --shared + $(MAKE) -C jim lib + +jim/libjim.a: + cd jim && CFLAGS="$(CFLAGS)" CC="$(CC)" ./configure $(JIM_CONFIGURE_OPTS) + $(MAKE) -C jim lib + +dispatcher-script: usb_modeswitch.tcl + sed 's_!/usr/bin/tclsh_!'"$(TCL)"'_' < usb_modeswitch.tcl > usb_modeswitch_dispatcher + +dispatcher-shared: jim/libjim.so dispatcher.c usb_modeswitch.string + $(CC) dispatcher.c $(LDFLAGS) -Ljim -ljim -Ijim -o usb_modeswitch_dispatcher $(CFLAGS) + +dispatcher-static: jim/libjim.a dispatcher.c usb_modeswitch.string + $(CC) dispatcher.c $(LDFLAGS) jim/libjim.a -Ijim -o usb_modeswitch_dispatcher $(CFLAGS) + +usb_modeswitch.string: usb_modeswitch.tcl + $(HOST_TCL) make_string.tcl usb_modeswitch.tcl > $@ + +clean: + $(RM) usb_modeswitch + $(RM) usb_modeswitch_dispatcher + $(RM) usb_modeswitch.string + $(RM) jim/autosetup/jimsh0 + $(RM) jim/autosetup/jimsh0.c + +distclean: clean + -$(MAKE) -C jim distclean + +ums-clean: + $(RM) usb_modeswitch + $(RM) usb_modeswitch_dispatcher + $(RM) usb_modeswitch.string + +# If the systemd folder is present, install the service for starting the dispatcher +# If not, use the dispatcher directly from the udev rule as in previous versions + +install-common: $(PROG) usb_modeswitch_dispatcher + install -D --mode=755 usb_modeswitch $(SBINDIR)/usb_modeswitch + install -D --mode=755 usb_modeswitch.sh $(UDEVDIR)/usb_modeswitch + install -D --mode=644 usb_modeswitch.conf $(ETCDIR)/usb_modeswitch.conf + install -D --mode=644 usb_modeswitch.1 $(MANDIR)/usb_modeswitch.1 + install -D --mode=644 usb_modeswitch_dispatcher.1 $(MANDIR)/usb_modeswitch_dispatcher.1 + install -D --mode=755 usb_modeswitch_dispatcher $(SBINDIR)/usb_modeswitch_dispatcher + install -d $(DESTDIR)/var/lib/usb_modeswitch + test -d $(UPSDIR) -a -e /sbin/initctl && install --mode=644 usb-modeswitch-upstart.conf $(UPSDIR) || test 1 + test -d $(SYSDIR) -a \( -e /usr/bin/systemctl -o -e /bin/systemctl \) && install --mode=644 usb_modeswitch@.service $(SYSDIR) || test 1 + +install: install-script + +install-script: dispatcher-script install-common + +install-shared: dispatcher-shared install-common + +install-static: dispatcher-static install-common + +uninstall: + $(RM) $(SBINDIR)/usb_modeswitch + $(RM) $(SBINDIR)/usb_modeswitch_dispatcher + $(RM) $(UDEVDIR)/usb_modeswitch + $(RM) $(ETCDIR)/usb_modeswitch.conf + $(RM) $(MANDIR)/usb_modeswitch.1 + $(RM) -R $(DESTDIR)/var/lib/usb_modeswitch + $(RM) $(SYSDIR)/usb_modeswitch@.service diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/README b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/README new file mode 100755 index 0000000..da6fb351 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/README @@ -0,0 +1,271 @@ +README for USB_ModeSwitch + +For up-to-date and more detailed information (plus a friendly forum) visit +http://www.draisberghof.de/usb_modeswitch + + +What it is +========== + +USB_ModeSwitch is - hardly surprising - a mode switching tool for controlling +USB devices with multiple "modes". Now, what does THAT mean? + +More and more USB devices have their MS Windows drivers onboard; when plugged +in for the first time they act like a flash storage and offer their driver +installation from there. +After installation (and on every consecutive plugging) the driver switches the +mode internally by sending a certain command sequence; the storage device +vanishes (in most cases) and a different device - like a USB modem - shows up. +To the host, this is like unplugging one device and then plugging annother. + +At first this feature appeared on devices with cell phone chipsets, presumably +because some of them were already able to change the mode of their USB port +from storage to communication - so why not make use of this in a modem stick? +Modem maker "Option" calls that feature "ZeroCD (TM)" since it eliminates the +need for shipping a separate driver carrier. + +In the beginning, nothing of this was documented in any form and there was +hardly any Linux/Unix support available. +On the good side, most of the known devices are working out of the box in all +modes with available Linux modules like "usb-storage" or serial USB drivers. +That leaves only the problem of the mode-switching from storage to whatever +the thing is supposed to do. + +Fortunately there are things like human smartness, USB sniffing programs and +LibUSB. The obvious way is to eavesdrop on the communication of the MS Windows +driver, to isolate the command or action that does the switching, and then re- +play the same sequence in a non-Windows system. + +In theory, this task could also be handled on the kernel driver level, but a +userspace program is much more flexible and can easily be disabled if access +to the initial mode of those devices should be desired. There has been a +principle decision by kernel developers to keep mode-switching outside of the +kernel. + +So USB_ModeSwitch has evolved to make this process easy to handle by taking the +relevant parameters from configuration files and handling all initialization +and communication business, with essential help from "libusb". + +In Linux and friends it is intended to work automatically - via udev events +and rules - and doing the mode switch without any user interaction. +However, the core C program should be as portable als libusb itself; it does not +rely on specific Linux features. +It can also be run as an interactive command line tool, particularly useful when +trying to tinker with hitherto unknown devices. + +We have already collected a wide range of information on how to mode-switch all +sorts of devices. If you run into a new one that is unknown yet, don't despair: +we can find out what you need to do! + + +How to install +============== + +If you only need the core C program, just run "make". All further steps de- +scribed below are referring to a common, fairly current Linux system where +USB_ModeSwitch is expected to do its work automatically. + +!! You need the usb-modeswitch-data package from the same source as this !! + +If you have an earlier version installed, de-installation is recommended ("make +uninstall") but not mandatory. The wrapper script location changed in 1.1.0; +old files might be orphaned but will not do any harm. + +The main prerequisite for installing from source is the development package for +"libusb". It may be called "libusb-dev" or similar in your distribution. From +usb_modeswitch 2.0.0 on, it should have an "1.x" in the name to reflect the change +to libusb-1. There are also variants around called "libusbx" if libusb-1 is not +available on your distribution. + +To install the tool set, unpack and run the install command (see below) in the +newly created directory. + +From version 1.2.0, there are three flavours of installing. The only difference +between those is the way the dispatcher is installed, but this affects the +dependencies as well: + +1. If you have the "Tcl" scripting language available on your system (packages + "tcl" or "jimsh"), use the light-weight installation: + + # make install + +2. If you are size-constrained and have the Jimsh library on your system + (package "libjim-dev"), you can have the Tcl interpreter embedded with the + dispatcher, using its shared lib: + + # make install-shared + +3. If you are size-constrained and definitely don't need a Tcl interpreter + for anything else, choose the statically embedded flavour. This will have + no further dependency as it uses the included interpreter code, which is + configured for small size: + + # make install-static + +Note that the "static"/"shared" targets are NOT referring to the usb_modeswitch +program, only to the dispatcher! +Any one of these commands will install a small posix shell script, the +dispatcher (wrapper) as script or as binary, a global config file, the core +program and a man page. + +Install the data package as well and you are set. + +NOTE: installing over (possibly outdated) Linux distribution packages of this +program and the data collection should not be a problem. + + +How to use +========== + +If your device is known, you should be able to just plug it and use it. If +it doesn't work - we will find out why. + +For manual use just run "usb_modeswitch" (as root). Work with the command +line interface or with a setup file. You can use any file and give its path +with the "-c" parameter. +The file named "device_reference.txt" that you can find on the home site of +this package is a device and configuration reference containing most known +devices; you can use it as a "database" to create your own configuration file. +It's heavily commented and should tell you what to do. It also contains a +thorough explanation of all the parameters. + +Run "usb_modeswitch -h" to list the command line parameters. +See also the provided man page. + +Important note: Manual use is mainly intended for testing and analyzing!! +The program puts no limits on what you can send to your USB device, so I +assume it is possible to screw it up profoundly. + +Once your new device is switching fine you can add it to the data files to +make the process automatic. + +For this to work, add a rule entry to the rules file to let udev run +usb_modeswitch as soon as the default IDs are found (when the device is +plugged). If you look into the rules file you will see immediately how +your new entry should look like. +The location is: +/lib/udev/rules.d/40-usb_modeswitch.rules + +Then add your new config file to the folder +"/etc/usb_modeswitch.d" (only for custom config files!). +And don't forget to report your success !! + +Again, remember that the rules file and the default device config folder +(/usr/share/usb_modeswitch) are installed by the usb_modeswitch data package. + + +########## +Important: libusb programs - like this tool - want to be run with administrative +privileges (as root or with sudo)! +########## + + + +Known working hardware, Troubleshooting +======================================= + +Please go to the homepage (see link at the top). Read carefully. +For support questions use ONLY public posts in the forum. + + + +Contribute +========== + +USB_ModeSwitch comes quite handy for experimenting with your own hardware if +not supported yet. You could try this approach: + +Note the device's vendor and product ID from /proc/bus/usb/devices (or from the +output of lsusb); the assigned driver is usually "usb-storage". Then try spying +on the USB communication to the device with the same ID inside MS Windoze. I +recommend this tool: +"SniffUSB" (http://benoit.papillault.free.fr/usbsnoop/index.php.en). + +PLEASE post any improvements, new device information and/or bug reports to the +forum (see above) or send it to the author (see below)! + + +Whodunit +======== + +Copyright 2007 - 2015 Josua Dietze (for non-support notifications write a personal +message through the forum to "Josh"; everything else only in a forum thread) + + !!! NO SUPPORT QUESTIONS VIA E-MAIL, use the forum !!! + +Major contributions: + +Command line parsing and other essential contributions: + Joakim Wennergren + +TargetClass parameter implementation to support new Option devices/firmware: + Paul Hardwick (http://www.pharscape.org) + +Created with initial help from: + "usbsnoop2libusb.pl" by Timo Lindfors + (http://iki.fi/lindi/usb/usbsnoop2libusb.pl) + +Config file parsing code borrowed from: + Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html) + +Hexstr2bin function borrowed from: + Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c") + +Indispensable help with device research and compilation: + Lars Melin + +Code, fixes and ideas contributed by: + Aki Makkonen + Denis Sutter + Lucas Benedicic + Roman Laube + Luigi Iotti + Vincent Teoh + Tommy Cheng + Daniel Cooper + Andrew Bird + Yaroslav Levandovskiy + Sakis Dimopoulos + Steven Fernandez + Christophe Fergeau + Nils Radtke + Filip Aben + Amit Mendapara + Roman S. Samarev + Chi-Hang Long + Andrey Tikhomirov + Daniel Mende + Nicholas Carrier + Adam Goode + Leonid Lisovskiy + Vladislav Grishenko + Daniel Drake + +Device information contributors are named in the "device_reference.txt" file. + +JimTcl is currently maintained by Steve Bennett; see README in subfolder + for details. It is released under a FreeBSD-style license. + Visit http://jim.tcl.tk/ + + + +Legal +===== + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details: + +http://www.gnu.org/licenses/gpl.txt + +Or find it as the file COPYING in this folder. + + + + +Last revised: 2016-06-12, Josua Dietze diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/dispatcher.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/dispatcher.c new file mode 100755 index 0000000..c38ae31 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/dispatcher.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011-2016 Josua Dietze, usb_modeswitch version 2.3.0 + * Contains code under + * Copyright (c) 2010 Wojciech A. Koszek <wkoszek@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <jim.h> + +/* RAW is defined to the complete Tcl code in that file: */ +#include "usb_modeswitch.string" + +#define MAX_ARGSIZE 1024 + +int main(int argc, char **argv) +{ + int i, retval; + char arg[MAX_ARGSIZE]; + char arglist[MAX_ARGSIZE]; + + Jim_Interp *interp; + + interp = NULL; + arglist[0] = '\0'; + + for (i=1; i<argc; i++) { + if (strlen(argv[i]) > MAX_ARGSIZE-4) { + printf("Argument #%d extends maximum size, skip it\n", i); + continue; + } + if ( (strlen(arglist) + strlen(argv[i])) > MAX_ARGSIZE-4) { + printf("Argument #%d would extend maximum list size, skip it\n", i); + continue; + } + sprintf(arg,"{%s} ",argv[i]); + strncat(arglist,arg,MAX_ARGSIZE-1); + } + + char code[sizeof(RAW) + sizeof(arglist) + 28]; + sprintf(code, "set argv {%s}\nset argc %d\n", arglist, argc-1); + strncat(code, RAW, sizeof(RAW)); + + /* Create Jim instance */ + interp = Jim_CreateInterp(); + assert(interp != NULL && "Could not create interpreter!"); + + /* Register base commands, actually implementing Tcl */ + Jim_RegisterCoreCommands(interp); + + /* Initialize any static extensions */ + Jim_InitStaticExtensions(interp); + + /* Evaluate the script that's now in "code" */ + retval = Jim_Eval(interp, code); + if (retval < 0) + printf("Evaluation returned error %d\n", retval); + + /* Free the interpreter */ + Jim_FreeInterp(interp); + return (EXIT_SUCCESS); +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/AUTHORS b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/AUTHORS new file mode 100755 index 0000000..73413a5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/AUTHORS @@ -0,0 +1,41 @@ +Salvatore Sanfilippo <antirez@invece.org> + +with the help (patches, bug reports, ideas, extensions) of: + +Pat Thoyts +Clemens Hintze + +See also the ChangeLog and README files for other credits. + +DESIGN CREDITS: + +some of the idea inside Jim are the fruit of long discussions +inside the Tclers chat room. The feedback of the Tcl +comunity in general, and of the members of the Tcl Core Team, was +very important to avoid mistakes: I used the great experience of +this people as a test for some of the ideas I put into Jim. +Bad ideas tend to be demolished in no time by good engineers. + +Also the following ideas are due to the following authors: + +- Jim locals were originally proposed by Miguel Sofer, I (SS) added + the feature that make they similar to lexical scoped closures + using capturing of the local variables value if no explicit + intialization is provided. + +- The [lmap] command is my (SS) design, but I incorporated inside the + command an interesting idea of Donal K. Fellows that proposed that + the [continue] command may be used to skip the accumulation of the + current-iteartion result, providing in one command the power of + [map] and [filter] together. + + +ChangeLog committers to be identified. Tentative list: + +antirez - Salvatore Sanfilippo <antirez@gmail.com> +patthoyts - Pat Thoyts <patthoyts@users.sf.net> +oharboe - �yvind Harboe - soyvind.harboe@zylin.com +Andrew Lunn <andrew@lunn.ch> +Duane Ellis <openocd@duaneellis.com> +Uwe Klein <uklein@klein-messgeraete.de> +Clemens Hintze ml-jim@qiao.in-berlin.de aka chi diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/LICENSE b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/LICENSE new file mode 100755 index 0000000..d5b9ecb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/LICENSE @@ -0,0 +1,45 @@ +Unless explicitly stated, all files within Jim repository are released +under following license: + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/Makefile.in b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/Makefile.in new file mode 100755 index 0000000..0191c83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/Makefile.in @@ -0,0 +1,198 @@ +# Tools +CC ?= @CCACHE@ @CC@ +CXX = @CCACHE@ @CXX@ +RANLIB = @RANLIB@ +AR = @AR@ +STRIP = @STRIP@ + +# Configuration + +SH_CFLAGS ?= @SH_CFLAGS@ +SH_LDFLAGS ?= @SH_LDFLAGS@ +SHOBJ_CFLAGS ?= @SHOBJ_CFLAGS@ +SHOBJ_LDFLAGS ?= @SHOBJ_LDFLAGS@ +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +LDFLAGS = @LDFLAGS@ +LDLIBS += @LDLIBS@ +exec_prefix ?= @exec_prefix@ +prefix ?= @prefix@ + +CC += -D_GNU_SOURCE -Wall $(OPTIM) -I. +CXX += -D_GNU_SOURCE -Wall $(OPTIM) -I. +@if srcdir != . +CFLAGS += -I@srcdir@ +CXXFLAGS += -I@srcdir@ +VPATH := @srcdir@ +@endif + +@if JIM_STATICLIB +LIBJIM := libjim.a +@else +LIBJIM := libjim.so +SH_LIBJIM := $(LIBJIM) +CC += $(SH_CFLAGS) +CXX += $(SH_CFLAGS) +DEF_LD_PATH := @LD_LIBRARY_PATH@=`pwd` +@endif + +@if HAVE_CXX_EXTENSIONS +JIMSH_CC := $(CXX) $(CXXFLAGS) +@else +JIMSH_CC := $(CC) $(CFLAGS) +@endif + +OBJS := _load-static-exts.o jim-subcmd.o jim-interactive.o jim-format.o jim.o utf8.o jimregexp.o \ + @EXTRA_OBJS@ @C_EXT_OBJS@ @TCL_EXT_OBJS@ + +JIMSH := jimsh@EXEEXT@ + +all: $(JIMSH) @C_EXT_SHOBJS@ + +# Create C extensions from pure Tcl extensions +.SUFFIXES: .tcl +.tcl.o: + @tclsh@ @srcdir@/make-c-ext.tcl $< >_$*.c || ( rm _$*.c; exit 1) + $(CC) $(CFLAGS) -c -o $@ _$*.c || ( rm _$*.c; exit 1) + @rm -f _$*.c + +docs: Tcl.html + +$(JIMSH): $(LIBJIM) jimsh.o initjimsh.o + $(JIMSH_CC) @SH_LINKFLAGS@ $(LDFLAGS) -o $@ jimsh.o initjimsh.o $(LIBJIM) $(LDLIBS) + +@if JIM_INSTALL +install: all docs @TCL_EXTS@ install-exec + mkdir -p $(DESTDIR)$(prefix)/lib/jim + cp $(LIBJIM) $(DESTDIR)$(prefix)/lib + cp @srcdir@/README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@ $(DESTDIR)$(prefix)/lib/jim + mkdir -p $(DESTDIR)$(prefix)/include + cp @srcdir@/jim.h @srcdir@/jim-eventloop.h @srcdir@/jim-nvp.h @srcdir@/jim-signal.h \ + @srcdir@/jim-subcmd.h @srcdir@/jim-win32compat.h $(DESTDIR)$(prefix)/include + cp jim-config.h $(DESTDIR)$(prefix)/include + mkdir -p $(DESTDIR)$(prefix)/doc/jim + cp Tcl.html $(DESTDIR)$(prefix)/doc/jim + +install-exec: all + mkdir -p $(DESTDIR)$(prefix)/bin + cp $(JIMSH) $(DESTDIR)$(prefix)/bin + +uninstall: + rm -f $(DESTDIR)$(prefix)/bin/$(JIMSH) + rm -f $(DESTDIR)$(prefix)/lib/$(LIBJIM) + for i in README.extensions @C_EXT_SHOBJS@ @TCL_EXTS@; do rm -f $(DESTDIR)$(prefix)/lib/jim/$$i; done + rm -f $(DESTDIR)$(prefix)/include/jim*.h + rm -f $(DESTDIR)$(prefix)/doc/jim/Tcl.html +@else +install install-exec uninstall: +@endif + +test: $(JIMSH) + $(DEF_LD_PATH) $(MAKE) -C @srcdir@/tests jimsh=`pwd`/jimsh + +$(OBJS): Makefile + +@if JIM_UTF8 +# Generate the unicode case mapping +utf8.o: _unicode_mapping.c + +_unicode_mapping.c: @srcdir@/UnicodeData.txt @srcdir@/parse-unidata.tcl + @tclsh@ @srcdir@/parse-unidata.tcl @srcdir@/UnicodeData.txt >$@ || ( rm $@; exit 1) +@endif + +_load-static-exts.c: @srcdir@/make-load-static-exts.tcl Makefile + @tclsh@ @srcdir@/make-load-static-exts.tcl @STATIC_EXTS@ >$@ || ( rm $@; exit 1) + +@if JIM_STATICLIB +$(LIBJIM): $(OBJS) + $(AR) cr $@ $(OBJS) + $(RANLIB) $@ +@else +$(LIBJIM): $(OBJS) + $(CC) $(CFLAGS) $(LDFLAGS) $(SH_LDFLAGS) -o $@ $(OBJS) $(LDLIBS) +@endif + +# Note that $> $^ is for compatibility with both GNU make and BSD make +readdir.so: jim-readdir.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readdir.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readdir.o $(SH_LIBJIM) + +array.so: jim-array.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-array.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-array.o $(SH_LIBJIM) + +clock.so: jim-clock.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-clock.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-clock.o $(SH_LIBJIM) + +file.so: jim-file.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-file.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-file.o $(SH_LIBJIM) + +posix.so: jim-posix.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-posix.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-posix.o $(SH_LIBJIM) + +regexp.so: jim-regexp.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-regexp.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-regexp.o $(SH_LIBJIM) + +syslog.so: jim-syslog.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-syslog.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-syslog.o $(SH_LIBJIM) + +readline.so: jim-readline.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-readline.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-readline.o $(SH_LIBJIM) @LDLIBS_readline@ + +pack.so: jim-pack.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-pack.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-pack.o $(SH_LIBJIM) @LDLIBS_pack@ + +sqlite.so: jim-sqlite.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sqlite.o $(SH_LIBJIM) @LDLIBS_sqlite@ + +sqlite3.so: jim-sqlite3.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sqlite3.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sqlite3.o $(SH_LIBJIM) @LDLIBS_sqlite3@ + +win32.so: jim-win32.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-win32.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-win32.o $(SH_LIBJIM) @LDLIBS_win32@ + +mk.so: jim-mk.cpp + $(CXX) $(CXXFLAGS) $(SHOBJ_CFLAGS) -c -o jim-mk.o $> $^ + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-mk.o $(SH_LIBJIM) @LDLIBS_mk@ + +sdl.so: jim-sdl.c + $(CC) $(CFLAGS) $(SHOBJ_CFLAGS) -c -o jim-sdl.o $> $^ + $(CC) $(CFLAGS) $(LDFLAGS) $(SHOBJ_LDFLAGS) -o $@ jim-sdl.o $(SH_LIBJIM) @LDLIBS_sdl@ + +Tcl.html: jim_tcl.txt + @tclsh@ @srcdir@/make-index $> $^ | asciidoc -o $@ -d manpage - || cp @srcdir@/Tcl_shipped.html Tcl.html + +clean: + rm -f *.o *.so lib*.a $(JIMSH) Tcl.html _*.c + +distclean: clean + rm -f jimautoconf.h jim-config.h Makefile config.log autosetup/jimsh0.c autosetup/jimsh0@EXEEXT@ + +ship: Tcl.html + cp $< Tcl_shipped.html + +# automake compatibility. do nothing for all these targets +EMPTY_AUTOMAKE_TARGETS := dvi pdf ps info html tags ctags mostlyclean maintainer-clean check installcheck installdirs \ + install-pdf install-ps install-info install-html -install-dvi uninstall install-data +.PHONY: $(EMPTY_AUTOMAKE_TARGETS) +$(EMPTY_AUTOMAKE_TARGETS): + +# automake compatibility - install sources from the current dir to $(distdir) +distdir_full := $(shell cd $(distdir); pwd) +distdir: + cd "@srcdir@"; git ls-files | cpio -pdmu $(distdir_full) + +reconfig: + CC='@CC@' @AUTOREMAKE@ + +lib: $(LIBJIM) diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README new file mode 100755 index 0000000..8acacc4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README @@ -0,0 +1,235 @@ +The Jim Interpreter + +A small-footprint implementation of the Tcl programming language. + +-------------------------------------------------------------------------------- +WHAT IS JIM? +-------------------------------------------------------------------------------- + +Jim is a small footprint implementation of the Tcl programming language +written from scratch. Currently Jim Tcl is very feature complete with +an extensive test suite (see the tests directory). +There are some Tcl commands and features which are not implemented +(and likely never will be), including namespaces, traces and Tk. However +Jim Tcl offers a number of both Tcl8.5 and Tcl8.6 features ({*}, dict, lassign, +tailcall and optional UTF-8 support) and some unique features. +These unique features include [lambda] with garbage collection, a general GC/references +system, arrays as syntax sugar for [dict]tionaries, object-based I/O and more. + +Other common features of the Tcl programming language are present, like +the "everything is a string" behaviour, implemented internally as +dual ported objects to ensure that the execution time does not reflect +the semantic of the language :) + +-------------------------------------------------------------------------------- +WHEN JIM CAN BE USEFUL? +-------------------------------------------------------------------------------- + +1) If you are writing an application, and want to make it scriptable, with +Jim you have a way to do it that does not require to link your application +with a big system. You can include the Jim source directly in your project +and use the Jim API to write the glue code that makes your application +scriptable in Jim, with the following advantages: + +- Jim is not the next "little language", but it's a Tcl implementation. + You can reuse your knowledge if you already Tcl skills, or enjoy + the availability of documentation, books, web resources, ... + (for example check my online Tcl book at http://www.invece.org/tclwise) + +- Jim is simple, 14k lines of core code. If you want to adapt it you can hack + the source code to meet the needs of your application. It makes you + able to have scripting for default, and avoid external dependences. + + Having scripting support *inside*, and in a way that a given version + of your program always gets shipped a given version of Jim, you can + write part of your application in Jim itself. Like it happens for + Emacs/Elisp, or Gimp/Scheme, both this applications have the interpreter + inside. + +- Jim is Tcl, and Tcl looks like a configuration file if you want. So + if you use Jim you have also a flexible syntax for your config file. + This is a valid Tcl script: + + set MyFeature on + ifssl { + set SslPort 45000 + use compression + } + + It looks like a configuration file, but if you implement the [ifssl] + and [use] commands, it's a valid Tcl script. + +- Tcl scales with the user. Not all know it, but Tcl is so powerful that + you can reprogram the language in itself. Jim support this features + of the Tcl programming language. You can write new control structures, + use the flexible data types it offers (Lists are a central data structure, + with Dictionaries that are also lists). Still Tcl is simpler for the + casual programmer, especially if compared to other languages offering + small footprint implementations (like Scheme and FORTH). + +- Because of the Tcl semantic (pass by value, everything is a command + since there are no reserved words), there is a nice API to glue + your application with Jim. See under the Jim Tcl manual for more detail. + +- Jim is supported. If you need commercial software, contact the original author + at 'antirez@gmail.com' or the current maintainer at 'steveb@workware.net.au'. + +2) The other "field" where Jim can be useful is obviously embedded systems. + +3) We are working to make Jim as feature-complete as possible, thanks to + dynamically loaded extensions it may stay as little as it is today + but able to do interesting things for you. So it's not excluded that + in the future Jim will be an option as general purpose language. + But don't mind, for this there is already the mainstream Tcl + implementation ;). + +-------------------------------------------------------------------------------- +HOW BIG IS IT? +-------------------------------------------------------------------------------- + +Jim with the default extensions configured and compiled with -Os is about 130k. +Without any extensions, it is about 85k. + +-------------------------------------------------------------------------------- +HOW FAST IS IT? +-------------------------------------------------------------------------------- + +Jim is in most code faster than Tcl7.6p2 (latest 7.x version), +and slower than Tcl 8.4.x. You can expect pretty decent performance +for such a little interpreter. + +If you want a more precise measure, there is 'bench.tcl' inside this +distribution that will run both under Jim and Tcl, so just execute +it with both the interpreters and see what you get :) + +-------------------------------------------------------------------------------- +HOW TO COMPILE +-------------------------------------------------------------------------------- + +Jim was tested under Linux, FreeBSD, MacosX, eCos, QNX, Windows XP (mingw, MVC). + +To compile jim itself try: + + ./configure + make + +-------------------------------------------------------------------------------- +EXTENSIONS +-------------------------------------------------------------------------------- + +Many optional extensions are included. Some are C extensions and others are pure Tcl. +Form more information, try: + + ./configure --help + +-------------------------------------------------------------------------------- +HOW TO EMBED JIM INTO APPLICATIONS +-------------------------------------------------------------------------------- + +See the "examples.api" directory + +-------------------------------------------------------------------------------- +HOW TO WRITE EXTENSIONS FOR JIM +-------------------------------------------------------------------------------- + +See the extensions shipped with Jim, jim-readline.c, jim-clock.c, glob.tcl and oo.tcl + +-------------------------------------------------------------------------------- +COPYRIGHT and LICENSE +-------------------------------------------------------------------------------- + +Unless explicitly stated, all files within Jim repository are released +under following license: + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + */ +-------------------------------------------------------------------------------- +HISTORY +-------------------------------------------------------------------------------- + +"first Jim goal: to vent my need to hack on Tcl." + +And actually this is exactly why I started Jim, in the first days +of Jenuary 2005. After a month of hacking Jim was able to run +simple scripts, now, after two months it started to be clear to +me that it was not just the next toy to throw away but something +that may evolve into a real interpreter. In the same time +Pat Thoyts and Clemens Hintze started to contribute code, so that +the development of new core commands was faster, and also more +people hacking on the same code had as result fixes in the API, +C macros, and so on. + +Currently we are at the point that the core interpreter is almost finished +and it is entering the Beta stage. There is to add some other core command, +to do a code review to ensure quality of all the parts and to write +documentation. + +We already started to work on extensions like OOP, event loop, +I/O, networking, regexp. Some extensions are already ready for +prime time, like the Sqlite extension and the ANSI I/O. + +------------------------------------------------------------------------------ +Thanks to... +------------------------------------------------------------------------------ + +- First of all, thanks to every guy that are listed in the AUTHORS file, + that directly helped with code and ideas. Also check the ChangeLog + file for additional credits about patches or bug reports. +- Elisa Manara that helped me to select this ill conceived name for + an interpreter. +- Many people on the Tclers Chat that helped me to explore issues + about the use and the implementation of the Tcl programming language. +- David Welton for the tech info sharing and our chats about + programming languages design and the ability of software to "scale down". +- Martin S. Weber for the great help with Solaris issues, debugging of + problems with [load] on this arch, 64bit tests. +- The authors of "valgrind", for this wonderful tool, that helped me a + lot to fix bugs in minutes instead of hours. + + +---- +Enjoy! +Salvatore Sanfilippo +10 Mar 2005 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch new file mode 100755 index 0000000..7f3ae41 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/README.usb_modeswitch @@ -0,0 +1,6 @@ +The content of this folder is customized for shipping with usb_modeswitch; +for the original source see: + +http://repo.or.cz/w/jimtcl.git + +This is version 0.72 of jimtcl diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/auto.def b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/auto.def new file mode 100755 index 0000000..2cdb85c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/auto.def @@ -0,0 +1,436 @@ +# vim:se syn=tcl: +# + +# Note: modules which support options *must* be included before 'options' +use cc cc-shared + +options { + utf8 => "include support for utf8-encoded strings" + lineedit=1 => "disable line editing" + references=1 => "disable support for references" + math => "include support for math functions" + ipv6 => "include ipv6 support in the aio extension" + maintainer => {enable the [debug] command and JimPanic} + full => "Enable some optional features: ipv6, math, utf8, binary, oo, tree" + with-jim-shared shared => "build a shared library instead of a static library" + jim-regexp => "use the built-in (Tcl-compatible) regexp, even if POSIX regex is available" + with-jim-ext: {with-ext:"ext1 ext2 ..."} => { + Specify additional jim extensions to include. + These are enabled by default: + + aio - ANSI I/O, including open and socket + eventloop - after, vwait, update + array - Tcl-compatible array command + clock - Tcl-compatible clock command + exec - Tcl-compatible exec command + file - Tcl-compatible file command + glob - Tcl-compatible glob command + readdir - Required for glob + package - Package management with the package command + load - Load binary extensions at runtime with load or package + posix - Posix APIs including os.fork, os.wait, pid + regexp - Tcl-compatible regexp, regsub commands + signal - Signal handling + stdlib - Built-in commands including lassign, lambda, alias + syslog - System logging with syslog + tclcompat - Tcl compatible read, gets, puts, parray, case, ... + + These are disabled by default: + + nvp - Name-value pairs C-only API + oo - Jim OO extension + tree - OO tree structure, similar to tcllib ::struct::tree + binary - Tcl-compatible 'binary' command + readline - Interface to libreadline + rlprompt - Tcl wrapper around the readline extension + mk - Interface to Metakit + sqlite - Interface to sqlite + sqlite3 - Interface to sqlite3 + win32 - Interface to win32 + } + with-out-jim-ext: {without-ext:"default|ext1 ext2 ..."} => { + Specify jim extensions to exclude. + If 'default' is given, the default extensions will not be added. + } + with-jim-extmod: {with-mod:"ext1 ext2 ..."} => { + Specify jim extensions to build as separate modules (either C or Tcl). + Note that not all extensions can be built as loadable modules. + } + # To help out openocd with automake + install-jim=1 +} + +cc-check-types "long long" + +cc-check-includes sys/socket.h netinet/in.h arpa/inet.h netdb.h +cc-check-includes sys/un.h dlfcn.h unistd.h crt_externs.h + +define LDLIBS "" + +# Haiku needs -lnetwork, Solaris needs -lnsl +if {[cc-check-function-in-lib inet_ntop {nsl network}]} { + # This does nothing if no libs are needed + cc-with [list -libs [get-define lib_inet_ntop]] + define-append LDLIBS [get-define lib_inet_ntop] +} +# Solaris needs -lsocket, Windows needs -lwsock32 +if {[cc-check-function-in-lib socket socket]} { + define-append LDLIBS [get-define lib_socket] +} + +cc-check-functions ualarm lstat fork vfork system select +cc-check-functions backtrace geteuid mkstemp realpath strptime gettimeofday +cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist +cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes +if {[cc-check-functions sysinfo]} { + cc-with {-includes sys/sysinfo.h} { + cc-check-members "struct sysinfo.uptime" + } +} + +define TCL_LIBRARY [get-define prefix]/lib/jim + +lassign [split [get-define host] -] host_cpu host_vendor host_os +# Scrub revision from the host_os +regsub -all {[0-9.]} $host_os {} host_os + +switch -glob -- $host_os { + mingw* { + # We provide our own implementation of dlopen for mingw32 + define-feature dlopen-compat + define-feature winconsole + define TCL_PLATFORM_OS $host_os + define TCL_PLATFORM_PLATFORM windows + define TCL_PLATFORM_PATH_SEPARATOR {;} + } + default { + # Note that cygwin is considered a unix platform + define TCL_PLATFORM_OS $host_os + define TCL_PLATFORM_PLATFORM unix + define TCL_PLATFORM_PATH_SEPARATOR : + } +} + +# Find some tools +cc-check-tools ar ranlib strip +define tclsh [info nameofexecutable] + +if {![cc-check-functions _NSGetEnviron]} { + msg-checking "Checking environ declared in unistd.h..." + if {[cctest -cflags -D_GNU_SOURCE -includes unistd.h -code {char **ep = environ;}]} { + define NO_ENVIRON_EXTERN + msg-result "yes" + } else { + msg-result "no" + } +} + +# Windows has a mkdir with no permission arg +cc-check-includes sys/types.h sys/stat.h +msg-checking "Checking for mkdir with one arg..." +if {[cctest -includes {sys/types.h sys/stat.h} -code {mkdir("/dummy");}]} { + define HAVE_MKDIR_ONE_ARG + msg-result yes +} else { + msg-result no +} + +# autosetup can't handle C++ libraries +proc check-metakit {} { + set found 0 + cc-with {-lang c++} { + msg-checking "Checking for Metakit..." + if {[cctest -includes mk4.h -libs -lmk4 -code {c4_Storage dummy();}]} { + msg-result ok + define lib_mk -lmk4 + incr found + } else { + msg-result "not found" + } + } + return $found +} + +set extra_objs {} +set jimregexp 0 + +if {[opt-bool utf8 full]} { + msg-result "Enabling UTF-8" + define JIM_UTF8 + incr jimregexp +} else { + define JIM_UTF8 0 +} +if {[opt-bool maintainer]} { + msg-result "Enabling maintainer settings" + define JIM_MAINTAINER +} +if {[opt-bool math full]} { + msg-result "Enabling math functions" + define JIM_MATH_FUNCTIONS + cc-check-function-in-lib sin m + define-append LDLIBS [get-define lib_sin] +} +if {[opt-bool ipv6 full]} { + msg-result "Enabling IPv6" + define JIM_IPV6 +} +if {[opt-bool lineedit full]} { + if {([cc-check-includes termios.h] && [cc-check-functions isatty]) || [have-feature winconsole]} { + msg-result "Enabling line editing" + define USE_LINENOISE + lappend extra_objs linenoise.o + } +} +if {[opt-bool references]} { + msg-result "Enabling references" + define JIM_REFERENCES +} +if {[opt-bool shared with-jim-shared]} { + msg-result "Building shared library" +} else { + msg-result "Building static library" + define JIM_STATICLIB +} +define JIM_INSTALL [opt-bool install-jim] + +# Note: Extension handling is mapped directly from the configure.ac +# implementation + +set without [join [opt-val {without-ext with-out-jim-ext}]] +set withext [join [opt-val {with-ext with-jim-ext}]] +set withmod [join [opt-val {with-mod with-jim-extmod}]] + +# Tcl extensions +set ext_tcl "stdlib glob tclcompat tree rlprompt oo binary" +# Native extensions +set ext_c "load package readdir array clock exec file posix regexp signal aio eventloop pack syslog nvp readline mk sqlite sqlite3 win32 sdl" + +# C++ extensions +set ext_cxx "mk" + +# Tcl extensions which can be modules +set ext_tcl_mod "glob tree rlprompt oo binary" +# Native extensions which can be modules +set ext_c_mod "readdir array clock file posix regexp syslog readline pack mk sqlite sqlite3 win32 sdl" + +# All extensions +set ext_all [concat $ext_c $ext_tcl] + +# Default static extensions +set ext_default "stdlib load package readdir glob array clock exec file posix regexp signal tclcompat aio eventloop syslog" + +if {[opt-bool full]} { + lappend ext_default tree binary +} + +if {$without eq "default"} { + set ext_default stdlib + set without {} +} + +# Check valid extension names +foreach i [concat $withext $without $withmod] { + if {$i ni $ext_all} { + user-error "Unknown extension: $i" + } +} + +# needs_xxx="expression" means that the expr must eval to 1 to select the extension +# dep_xxx="yyy zzz" means that if xxx is selected, so is yyy and zzz +set dep(glob) readdir +set dep(rlprompt) readline +set dep(tree) oo +set dep(binary) pack + +set needs(exec) {expr {([have-feature vfork] && [have-feature waitpid]) || [have-feature system]}} +set needs(load) {expr {[cc-check-function-in-lib dlopen dl] || [have-feature dlopen-compat]}} +set libdep(load) lib_dlopen +set needs(posix) {have-feature waitpid} +set needs(readdir) {have-feature opendir} +set needs(readline) {cc-check-function-in-lib readline readline} +set libdep(readline) lib_readline +set needs(signal) {expr {[have-feature sigaction] && [have-feature vfork]}} +set needs(mk) {check-metakit} +set libdep(mk) lib_mk +set needs(sqlite) {cc-check-function-in-lib sqlite_open sqlite} +set libdep(sqlite) lib_sqlite_open +set needs(sqlite3) {cc-check-function-in-lib sqlite3_open sqlite3} +set libdep(sqlite3) lib_sqlite3_open +set needs(syslog) {have-feature syslog} +set needs(win32) {have-feature windows} +set needs(sdl) {expr {[cc-check-function-in-lib SDL_SetVideoMode SDL] && [cc-check-function-in-lib rectangleRGBA SDL_gfx]}} +set libdep(sdl) {lib_SDL_SetVideoMode lib_rectangleRGBA} + +# First handle dependencies. If an extension is enabled, also enable its dependency +foreach i [concat $ext_default $withext] { + if {$i in $without} { + continue + } + if {[info exists dep($i)]} { + lappend withext {*}$dep($i) + } +} + +foreach i $withmod { + if {[info exists dep($i)]} { + # Theoretically, a mod could depend upon something which must be static + # If already configured static, don't make it a module + foreach d $dep($i) { + if {$d ni $withext} { + lappend withmod $d + } + } + } +} + +# Now that we know what the platform supports: + +# For all known extensions: +# - If it is disabled, remove it +# - Otherwise, check to see if it's pre-requisites are met +# - If yes, add it if it is enabled or is a default +# - If no, error if it is enabled, or do nothing otherwise +# - Modules may be either C or Tcl + +set extmodtcl {} +set extmod {} +set ext {} + +foreach i [lsort $ext_all] { + # First discard the extension if disabled or not enabled + if {$i in $without} { + msg-result "Extension $i...disabled" + continue + } + if {$i ni [concat $withext $withmod $ext_default]} { + msg-result "Extension $i...not enabled" + continue + } + + # Check dependencies + set met 1 + if {[info exists needs($i)]} { + set met [eval $needs($i)] + } + + define LDLIBS_$i "" + + msg-checking "Extension $i..." + + # Selected as a module? + if {$i in $withmod} { + if {$i in $ext_tcl_mod} { + # Easy, a Tcl module + msg-result "tcl" + lappend extmodtcl $i + continue + } + if {$i ni $ext_c_mod} { + user-error "not a module" + } + if {!$met} { + user-error "dependencies not met" + } + msg-result "module" + lappend extmod $i + if {[info exists libdep($i)]} { + foreach j $libdep($i) { + define-append LDLIBS_$i [get-define $j ""] + } + } + continue + } + + # Selected as a static extension? + if {$i in $withext} { + if {!$met} { + user-error "dependencies not met" + } + msg-result "enabled" + } elseif {$i in $ext_default} { + if {!$met} { + msg-result "disabled (dependencies)" + continue + } + msg-result "enabled (default)" + } else { + continue + } + + lappend ext $i + if {[info exists libdep($i)]} { + foreach j $libdep($i) { + define-append LDLIBS [get-define $j ""] + } + } +} + +if {[have-feature windows]} { + lappend extra_objs jim-win32compat.o + + if {$extmod ne "" && [get-define JIM_LIBTYPE] eq "static"} { + user-error "cygwin/mingw require --shared for dynamic modules" + } +} + +if {"regexp" in "$ext $extmod"} { + # No regcomp means we need to use the built-in version + if {![have-feature regcomp]} { + incr jimregexp + } +} + +if {$jimregexp || [opt-bool jim-regexp]} { + msg-result "Using built-in regexp" + define JIM_REGEXP + + # If the built-in regexp overrides the system regcomp, etc. + # jim must be built shared so that the correct symbols are found + if {"regexp" in $extmod && [get-define JIM_LIBTYPE] eq "static" && [have-feature regcomp]} { + user-error "Must use --shared with regexp module and built-in regexp" + } +} +if {"load" ni $ext} { + # If we don't have load, no need to support shared objects + define SH_LINKFLAGS "" +} + +msg-result "Jim static extensions: [lsort $ext]" +if {$extmodtcl ne ""} { + msg-result "Jim Tcl extensions: [lsort $extmodtcl]" +} +if {$extmod ne ""} { + msg-result "Jim dynamic extensions: [lsort $extmod]" +} + +# Separate out the static extensions into C and Tcl +set ext_static_c {} +set ext_static_tcl {} +foreach e $ext { + define jim_ext_$e + if {$e in $ext_tcl} { + lappend ext_static_tcl $e + } else { + lappend ext_static_c $e + } +} + +# If there are any static C++ extensions, jimsh must be linked using +# the C++ compiler +foreach e $ext_static_c { + if {$e in $ext_cxx} { + define HAVE_CXX_EXTENSIONS + } +} + +define STATIC_EXTS [concat $ext_static_c $ext_static_tcl] +define C_EXT_OBJS [prefix jim- [suffix .o $ext_static_c]] +define TCL_EXT_OBJS [suffix .o $ext_static_tcl] +define C_EXT_SHOBJS [suffix .so $extmod] +define TCL_EXTS [suffix .tcl $extmodtcl] +define EXTRA_OBJS $extra_objs + +make-config-header jim-config.h -auto {HAVE_LONG_LONG* JIM_UTF8} -none * +make-config-header jimautoconf.h -auto {jim_ext_* TCL_PLATFORM_* TCL_LIBRARY USE_* JIM_*} +make-template Makefile.in diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE new file mode 100755 index 0000000..4fe636c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/LICENSE @@ -0,0 +1,35 @@ +Unless explicitly stated, all files which form part of autosetup +are released under the following license: + +--------------------------------------------------------------------- +autosetup - A build environment "autoconfigurator" + +Copyright (c) 2010-2011, WorkWare Systems <http://workware.net.au/> + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE +SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of WorkWare Systems. diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup new file mode 100755 index 0000000..c7f69a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/README.autosetup @@ -0,0 +1 @@ +This is autosetup v0.6.3. See http://msteveb.github.com/autosetup/ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup new file mode 100755 index 0000000..b1134c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/autosetup @@ -0,0 +1,1820 @@ +#!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: +# \ +dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" + +set autosetup(version) 0.6.3 + +# Can be set to 1 to debug early-init problems +set autosetup(debug) 0 + +################################################################## +# +# Main flow of control, option handling +# +proc main {argv} { + global autosetup define + + # There are 3 potential directories involved: + # 1. The directory containing autosetup (this script) + # 2. The directory containing auto.def + # 3. The current directory + + # From this we need to determine: + # a. The path to this script (and related support files) + # b. The path to auto.def + # c. The build directory, where output files are created + + # This is also complicated by the fact that autosetup may + # have been run via the configure wrapper ([getenv WRAPPER] is set) + + # Here are the rules. + # a. This script is $::argv0 + # => dir, prog, exe, libdir + # b. auto.def is in the directory containing the configure wrapper, + # otherwise it is in the current directory. + # => srcdir, autodef + # c. The build directory is the current directory + # => builddir, [pwd] + + # 'misc' is needed before we can do anything, so set a temporary libdir + # in case this is the development version + set autosetup(libdir) [file dirname $::argv0]/lib + use misc + + # (a) + set autosetup(dir) [realdir [file dirname [realpath $::argv0]]] + set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]] + set autosetup(exe) [getenv WRAPPER $autosetup(prog)] + if {$autosetup(installed)} { + set autosetup(libdir) $autosetup(dir) + } else { + set autosetup(libdir) [file join $autosetup(dir) lib] + } + autosetup_add_dep $autosetup(prog) + + # (b) + if {[getenv WRAPPER ""] eq ""} { + # Invoked directly + set autosetup(srcdir) [pwd] + } else { + # Invoked via the configure wrapper + set autosetup(srcdir) [file dirname $autosetup(exe)] + } + set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def] + + # (c) + set autosetup(builddir) [pwd] + + set autosetup(argv) $argv + set autosetup(cmdline) {} + set autosetup(options) {} + set autosetup(optionhelp) {} + set autosetup(showhelp) 0 + + # Parse options + use getopt + + array set ::useropts [getopt argv] + + #"=Core Options:" + options-add { + help:=local => "display help and options. Optionally specify a module name, such as --help=system" + version => "display the version of autosetup" + ref:=text manual:=text + reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'" + debug => "display debugging output as autosetup runs" + install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)" + force init => "create an initial 'configure' script if none exists" + # Undocumented options + option-checking=1 + nopager + quiet + timing + conf: + } + + #parray ::useropts + if {[opt-bool version]} { + puts $autosetup(version) + exit 0 + } + + # autosetup --conf=alternate-auto.def + if {[opt-val conf] ne ""} { + set autosetup(autodef) [opt-val conf] + } + + # Debugging output (set this early) + incr autosetup(debug) [opt-bool debug] + incr autosetup(force) [opt-bool force] + incr autosetup(msg-quiet) [opt-bool quiet] + incr autosetup(msg-timing) [opt-bool timing] + + # If the local module exists, source it now to allow for + # project-local customisations + if {[file exists $autosetup(libdir)/local.tcl]} { + use local + } + + if {[opt-val help] ne ""} { + incr autosetup(showhelp) + use help + autosetup_help [opt-val help] + } + + if {[opt-val {manual ref reference}] ne ""} { + use help + autosetup_reference [opt-val {manual ref reference}] + } + + if {[opt-bool init]} { + use init + autosetup_init + } + + if {[opt-val install] ne ""} { + use install + autosetup_install [opt-val install] + } + + if {![file exists $autosetup(autodef)]} { + # Check for invalid option first + options {} + user-error "No auto.def found in $autosetup(srcdir)" + } + + # Parse extra arguments into autosetup(cmdline) + foreach arg $argv { + if {[regexp {([^=]*)=(.*)} $arg -> n v]} { + dict set autosetup(cmdline) $n $v + define $n $v + } else { + user-error "Unexpected parameter: $arg" + } + } + + autosetup_add_dep $autosetup(autodef) + + set cmd [file-normalize $autosetup(exe)] + foreach arg $autosetup(argv) { + append cmd " [quote-if-needed $arg]" + } + define AUTOREMAKE $cmd + + # Log how we were invoked + configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" + + source $autosetup(autodef) + + # Could warn here if options {} was not specified + + show-notices + + if {$autosetup(debug)} { + parray define + } + + exit 0 +} + +# @opt-bool option ... +# +# Check each of the named, boolean options and return 1 if any of them have +# been set by the user. +# +proc opt-bool {args} { + option-check-names {*}$args + opt_bool ::useropts {*}$args +} + +# @opt-val option-list ?default=""? +# +# Returns a list containing all the values given for the non-boolean options in 'option-list'. +# There will be one entry in the list for each option given by the user, including if the +# same option was used multiple times. +# If only a single value is required, use something like: +# +## lindex [opt-val $names] end +# +# If no options were set, $default is returned (exactly, not as a list). +# +proc opt-val {names {default ""}} { + option-check-names {*}$names + join [opt_val ::useropts $names $default] +} + +proc option-check-names {args} { + foreach o $args { + if {$o ni $::autosetup(options)} { + autosetup-error "Request for undeclared option --$o" + } + } +} + +# Parse the option definition in $opts and update +# ::useropts() and ::autosetup(optionhelp) appropriately +# +proc options-add {opts {header ""}} { + global useropts autosetup + + # First weed out comment lines + set realopts {} + foreach line [split $opts \n] { + if {![string match "#*" [string trimleft $line]]} { + append realopts $line \n + } + } + set opts $realopts + + for {set i 0} {$i < [llength $opts]} {incr i} { + set opt [lindex $opts $i] + if {[string match =* $opt]} { + # This is a special heading + lappend autosetup(optionhelp) $opt "" + set header {} + continue + } + + #puts "i=$i, opt=$opt" + regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value + if {$name in $autosetup(options)} { + autosetup-error "Option $name already specified" + } + + #puts "$opt => $name $colon $equal $value" + + # Find the corresponding value in the user options + # and set the default if necessary + if {[string match "-*" $opt]} { + # This is a documentation-only option, like "-C <dir>" + set opthelp $opt + } elseif {$colon eq ""} { + # Boolean option + lappend autosetup(options) $name + + if {![info exists useropts($name)]} { + set useropts($name) $value + } + if {$value eq "1"} { + set opthelp "--disable-$name" + } else { + set opthelp "--$name" + } + } else { + # String option. + lappend autosetup(options) $name + + if {$equal eq "="} { + if {[info exists useropts($name)]} { + # If the user specified the option with no value, the value will be "1" + # Replace with the default + if {$useropts($name) eq "1"} { + set useropts($name) $value + } + } + set opthelp "--$name?=$value?" + } else { + set opthelp "--$name=$value" + } + } + + # Now create the help for this option if appropriate + if {[lindex $opts $i+1] eq "=>"} { + set desc [lindex $opts $i+2] + #string match \n* $desc + if {$header ne ""} { + lappend autosetup(optionhelp) $header "" + set header "" + } + # A multi-line description + lappend autosetup(optionhelp) $opthelp $desc + incr i 2 + } + } +} + +# @module-options optionlist +# +# Like 'options', but used within a module. +proc module-options {opts} { + set header "" + if {$::autosetup(showhelp) > 1 && [llength $opts]} { + set header "Module Options:" + } + options-add $opts $header + + if {$::autosetup(showhelp)} { + # Ensure that the module isn't executed on --help + # We are running under eval or source, so use break + # to prevent further execution + #return -code break -level 2 + return -code break + } +} + +proc max {a b} { + expr {$a > $b ? $a : $b} +} + +proc options-wrap-desc {text length firstprefix nextprefix initial} { + set len $initial + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} + +proc options-show {} { + # Determine the max option width + set max 0 + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt] || [string match \n* $desc]} { + continue + } + set max [max $max [string length $opt]] + } + set indent [string repeat " " [expr $max+4]] + set cols [getenv COLUMNS 80] + catch { + lassign [exec stty size] rows cols + } + incr cols -1 + # Now output + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt]} { + puts [string range $opt 1 end] + continue + } + puts -nonewline " [format %-${max}s $opt]" + if {[string match \n* $desc]} { + puts $desc + } else { + options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2] + } + } +} + +# @options options-spec +# +# Specifies configuration-time options which may be selected by the user +# and checked with opt-val and opt-bool. The format of options-spec follows. +# +# A boolean option is of the form: +# +## name[=0|1] => "Description of this boolean option" +# +# The default is name=0, meaning that the option is disabled by default. +# If name=1 is used to make the option enabled by default, the description should reflect +# that with text like "Disable support for ...". +# +# An argument option (one which takes a parameter) is of the form: +# +## name:[=]value => "Description of this option" +# +# If the name:value form is used, the value must be provided with the option (as --name=myvalue). +# If the name:=value form is used, the value is optional and the given value is used as the default +# if is not provided. +# +# Undocumented options are also supported by omitting the "=> description. +# These options are not displayed with --help and can be useful for internal options or as aliases. +# +# For example, --disable-lfs is an alias for --disable=largefile: +# +## lfs=1 largefile=1 => "Disable large file support" +# +proc options {optlist} { + # Allow options as a list or args + options-add $optlist "Local Options:" + + if {$::autosetup(showhelp)} { + options-show + exit 0 + } + + # Check for invalid options + if {[opt-bool option-checking]} { + foreach o [array names ::useropts] { + if {$o ni $::autosetup(options)} { + user-error "Unknown option --$o" + } + } + } +} + +proc config_guess {} { + if {[file-isexec $::autosetup(dir)/config.guess]} { + exec-with-stderr sh $::autosetup(dir)/config.guess + } else { + configlog "No config.guess, so using uname" + string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r] + } +} + +proc config_sub {alias} { + if {[file-isexec $::autosetup(dir)/config.sub]} { + exec-with-stderr sh $::autosetup(dir)/config.sub $alias + } else { + return $alias + } +} + +# @define name ?value=1? +# +# Defines the named variable to the given value. +# These (name, value) pairs represent the results of the configuration check +# and are available to be checked, modified and substituted. +# +proc define {name {value 1}} { + set ::define($name) $value + #dputs "$name <= $value" +} + +# @define-append name value ... +# +# Appends the given value(s) to the given 'defined' variable. +# If the variable is not defined or empty, it is set to $value. +# Otherwise the value is appended, separated by a space. +# Any extra values are similarly appended. +# If any value is already contained in the variable (as a substring) it is omitted. +# +proc define-append {name args} { + if {[get-define $name ""] ne ""} { + # Make a token attempt to avoid duplicates + foreach arg $args { + if {[string first $arg $::define($name)] == -1} { + append ::define($name) " " $arg + } + } + } else { + set ::define($name) [join $args] + } + #dputs "$name += [join $args] => $::define($name)" +} + +# @get-define name ?default=0? +# +# Returns the current value of the 'defined' variable, or $default +# if not set. +# +proc get-define {name {default 0}} { + if {[info exists ::define($name)]} { + #dputs "$name => $::define($name)" + return $::define($name) + } + #dputs "$name => $default" + return $default +} + +# @is-defined name +# +# Returns 1 if the given variable is defined. +# +proc is-defined {name} { + info exists ::define($name) +} + +# @all-defines +# +# Returns a dictionary (name value list) of all defined variables. +# +# This is suitable for use with 'dict', 'array set' or 'foreach' +# and allows for arbitrary processing of the defined variables. +# +proc all-defines {} { + array get ::define +} + + +# @get-env name default +# +# If $name was specified on the command line, return it. +# If $name was set in the environment, return it. +# Otherwise return $default. +# +proc get-env {name default} { + if {[dict exists $::autosetup(cmdline) $name]} { + return [dict get $::autosetup(cmdline) $name] + } + getenv $name $default +} + +# @env-is-set name +# +# Returns 1 if the $name was specified on the command line or in the environment. +# Note that an empty environment variable is not considered to be set. +# +proc env-is-set {name} { + if {[dict exists $::autosetup(cmdline) $name]} { + return 1 + } + if {[getenv $name ""] ne ""} { + return 1 + } + return 0 +} + +# @readfile filename ?default=""? +# +# Return the contents of the file, without the trailing newline. +# If the doesn't exist or can't be read, returns $default. +# +proc readfile {filename {default_value ""}} { + set result $default_value + catch { + set f [open $filename] + set result [read -nonewline $f] + close $f + } + return $result +} + +# @writefile filename value +# +# Creates the given file containing $value. +# Does not add an extra newline. +# +proc writefile {filename value} { + set f [open $filename w] + puts -nonewline $f $value + close $f +} + +proc quote-if-needed {str} { + if {[string match {*[\" ]*} $str]} { + return \"[string map [list \" \\" \\ \\\\] $str]\" + } + return $str +} + +proc quote-argv {argv} { + set args {} + foreach arg $argv { + lappend args [quote-if-needed $arg] + } + join $args +} + +# @suffix suf list +# +# Takes a list and returns a new list with $suf appended +# to each element +# +## suffix .c {a b c} => {a.c b.c c.c} +# +proc suffix {suf list} { + set result {} + foreach p $list { + lappend result $p$suf + } + return $result +} + +# @prefix pre list +# +# Takes a list and returns a new list with $pre prepended +# to each element +# +## prefix jim- {a.c b.c} => {jim-a.c jim-b.c} +# +proc prefix {pre list} { + set result {} + foreach p $list { + lappend result $pre$p + } + return $result +} + +# @find-executable name +# +# Searches the path for an executable with the given name. +# Note that the name may include some parameters, e.g. "cc -mbig-endian", +# in which case the parameters are ignored. +# Returns 1 if found, or 0 if not. +# +proc find-executable {name} { + # Ignore any parameters + set name [lindex $name 0] + if {$name eq ""} { + # The empty string is never a valid executable + return 0 + } + foreach p [split-path] { + dputs "Looking for $name in $p" + set exec [file join $p $name] + if {[file-isexec $exec]} { + dputs "Found $name -> $exec" + return 1 + } + } + return 0 +} + +# @find-an-executable ?-required? name ... +# +# Given a list of possible executable names, +# searches for one of these on the path. +# +# Returns the name found, or "" if none found. +# If the first parameter is '-required', an error is generated +# if no executable is found. +# +proc find-an-executable {args} { + set required 0 + if {[lindex $args 0] eq "-required"} { + set args [lrange $args 1 end] + incr required + } + foreach name $args { + if {[find-executable $name]} { + return $name + } + } + if {$required} { + if {[llength $args] == 1} { + user-error "failed to find: [join $args]" + } else { + user-error "failed to find one of: [join $args]" + } + } + return "" +} + +# @configlog msg +# +# Writes the given message to the configuration log, config.log +# +proc configlog {msg} { + if {![info exists ::autosetup(logfh)]} { + set ::autosetup(logfh) [open config.log w] + } + puts $::autosetup(logfh) $msg +} + +# @msg-checking msg +# +# Writes the message with no newline to stdout. +# +proc msg-checking {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts -nonewline $msg + set ::autosetup(msg-checking) 1 + } +} + +# @msg-result msg +# +# Writes the message to stdout. +# +proc msg-result {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts $msg + set ::autosetup(msg-checking) 0 + show-notices + } +} + +# @msg-quiet command ... +# +# msg-quiet evaluates it's arguments as a command with output +# from msg-checking and msg-result suppressed. +# +# This is useful if a check needs to run a subcheck which isn't +# of interest to the user. +proc msg-quiet {args} { + incr ::autosetup(msg-quiet) + set rc [uplevel 1 $args] + incr ::autosetup(msg-quiet) -1 + return $rc +} + +# Will be overridden by 'use misc' +proc error-stacktrace {msg} { + return $msg +} + +proc error-location {msg} { + return $msg +} + +################################################################## +# +# Debugging output +# +proc dputs {msg} { + if {$::autosetup(debug)} { + puts $msg + } +} + +################################################################## +# +# User and system warnings and errors +# +# Usage errors such as wrong command line options + +# @user-error msg +# +# Indicate incorrect usage to the user, including if required components +# or features are not found. +# autosetup exits with a non-zero return code. +# +proc user-error {msg} { + show-notices + puts stderr "Error: $msg" + puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options" + exit 1 +} + +# @user-notice msg +# +# Output the given message to stderr. +# +proc user-notice {msg} { + lappend ::autosetup(notices) $msg +} + +# Incorrect usage in the auto.def file. Identify the location. +proc autosetup-error {msg} { + show-notices + puts stderr [error-location $msg] + exit 1 +} + +proc show-notices {} { + if {$::autosetup(msg-checking)} { + puts "" + set ::autosetup(msg-checking) 0 + } + flush stdout + if {[info exists ::autosetup(notices)]} { + puts stderr [join $::autosetup(notices) \n] + unset ::autosetup(notices) + } +} + +proc maybe-show-timestamp {} { + if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} { + puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]] + } +} + +proc autosetup_version {} { + return "autosetup v$::autosetup(version)" +} + +################################################################## +# +# Directory/path handling +# + +proc realdir {dir} { + set oldpwd [pwd] + cd $dir + set pwd [pwd] + cd $oldpwd + return $pwd +} + +# Follow symlinks until we get to something which is not a symlink +proc realpath {path} { + while {1} { + if {[catch { + set path [file link $path] + }]} { + # Not a link + break + } + } + return $path +} + +# Convert absolute path, $path into a path relative +# to the given directory (or the current dir, if not given). +# +proc relative-path {path {pwd {}}} { + set diff 0 + set same 0 + set newf {} + set prefix {} + set path [file-normalize $path] + if {$pwd eq ""} { + set pwd [pwd] + } else { + set pwd [file-normalize $pwd] + } + + if {$path eq $pwd} { + return . + } + + # Try to make the filename relative to the current dir + foreach p [split $pwd /] f [split $path /] { + if {$p ne $f} { + incr diff + } elseif {!$diff} { + incr same + } + if {$diff} { + if {$p ne ""} { + # Add .. for sibling or parent dir + lappend prefix .. + } + if {$f ne ""} { + lappend newf $f + } + } + } + if {$same == 1 || [llength $prefix] > 3} { + return $path + } + + file join [join $prefix /] [join $newf /] +} + +# Add filename as a dependency to rerun autosetup +# The name will be normalised (converted to a full path) +# +proc autosetup_add_dep {filename} { + lappend ::autosetup(deps) [file-normalize $filename] +} + +################################################################## +# +# Library module support +# + +# @use module ... +# +# Load the given library modules. +# e.g. use cc cc-shared +# +proc use {args} { + foreach m $args { + if {[info exists ::libmodule($m)]} { + continue + } + set ::libmodule($m) 1 + if {[info exists ::modsource($m)]} { + uplevel #0 eval $::modsource($m) + } else { + set source $::autosetup(libdir)/${m}.tcl + if {[file exists $source]} { + uplevel #0 [list source $source] + autosetup_add_dep $source + } else { + puts "Looking for $source" + autosetup-error "use: No such module: $m" + } + } + } +} + +# Initial settings +set autosetup(exe) $::argv0 +set autosetup(istcl) 1 +set autosetup(start) [clock millis] +set autosetup(installed) 0 +set autosetup(msg-checking) 0 +set autosetup(msg-quiet) 0 + +# Embedded modules are inserted below here +set autosetup(installed) 1 +# ----- module asciidoc-formatting ----- + +set modsource(asciidoc-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# asciidoc format + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc code {text} { + foreach line [parse_code_block $text] { + puts " $line" + } + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc indent {text} { + puts " :: " + puts [para $text] +} +proc defn {first args} { + set sep "" + if {$first ne ""} { + puts "${first}::" + } else { + puts " :: " + } + set defn [string trim [join $args \n]] + regsub -all "\n\n" $defn "\n ::\n" defn + puts $defn +} +} + +# ----- module formatting ----- + +set modsource(formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides common text formatting + +# This is designed for documenation which looks like: +# code {...} +# or +# code { +# ... +# ... +# } +# In the second case, we need to work out the indenting +# and strip it from all lines but preserve the remaining indenting. +# Note that all lines need to be indented with the same initial +# spaces/tabs. +# +# Returns a list of lines with the indenting removed. +# +proc parse_code_block {text} { + # If the text begins with newline, take the following text, + # otherwise just return the original + if {![regexp "^\n(.*)" $text -> text]} { + return [list [string trim $text]] + } + + # And trip spaces off the end + set text [string trimright $text] + + set min 100 + # Examine each line to determine the minimum indent + foreach line [split $text \n] { + if {$line eq ""} { + # Ignore empty lines for the indent calculation + continue + } + regexp "^(\[ \t\]*)" $line -> indent + set len [string length $indent] + if {$len < $min} { + set min $len + } + } + + # Now make a list of lines with this indent removed + set lines {} + foreach line [split $text \n] { + lappend lines [string range $line $min end] + } + + # Return the result + return $lines +} +} + +# ----- module getopt ----- + +set modsource(getopt) { +# Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Simple getopt module + +# Parse everything out of the argv list which looks like an option +# Knows about --enable-thing and --disable-thing as alternatives for --thing=0 or --thing=1 +# Everything which doesn't look like an option, or is after --, is left unchanged +proc getopt {argvname} { + upvar $argvname argv + set nargv {} + + for {set i 0} {$i < [llength $argv]} {incr i} { + set arg [lindex $argv $i] + + #dputs arg=$arg + + if {$arg eq "--"} { + # End of options + incr i + lappend nargv {*}[lrange $argv $i end] + break + } + + if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} { + lappend opts($name) $value + } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} { + if {$prefix eq "disable-"} { + set value 0 + } else { + set value 1 + } + lappend opts($name) $value + } else { + lappend nargv $arg + } + } + + #puts "getopt: argv=[join $argv] => [join $nargv]" + #parray opts + + set argv $nargv + + return [array get opts] +} + +proc opt_val {optarrayname options {default {}}} { + upvar $optarrayname opts + + set result {} + + foreach o $options { + if {[info exists opts($o)]} { + lappend result {*}$opts($o) + } + } + if {[llength $result] == 0} { + return $default + } + return $result +} + +proc opt_bool {optarrayname args} { + upvar $optarrayname opts + + # Support the args being passed as a list + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + foreach o $args { + if {[info exists opts($o)]} { + if {"1" in $opts($o) || "yes" in $opts($o)} { + return 1 + } + } + } + return 0 +} +} + +# ----- module help ----- + +set modsource(help) { +# Copyright (c) 2010 WorkWare Systems http://workware.net.au/ +# All rights reserved + +# Module which provides usage, help and the command reference + +proc autosetup_help {what} { + use_pager + + puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" + puts "This is [autosetup_version], a build environment \"autoconfigurator\"" + puts "See the documentation online at http://msteveb.github.com/autosetup/\n" + + if {$what eq "local"} { + if {[file exists $::autosetup(autodef)]} { + # This relies on auto.def having a call to 'options' + # which will display options and quit + source $::autosetup(autodef) + } else { + options-show + } + } else { + incr ::autosetup(showhelp) + if {[catch {use $what}]} { + user-error "Unknown module: $what" + } else { + options-show + } + } + exit 0 +} + +# If not already paged and stdout is a tty, pipe the output through the pager +# This is done by reinvoking autosetup with --nopager added +proc use_pager {} { + if {![opt-bool nopager] && [getenv PAGER ""] ne "" && ![string match "not a tty" [exec tty]]} { + catch { + exec [info nameofexecutable] $::argv0 --nopager {*}$::argv | [getenv PAGER] >@stdout <@stdin 2>/dev/null + } + exit 0 + } +} + +# Outputs the autosetup references in one of several formats +proc autosetup_reference {{type text}} { + + use_pager + + switch -glob -- $type { + wiki {use wiki-formatting} + ascii* {use asciidoc-formatting} + md - markdown {use markdown-formatting} + default {use text-formatting} + } + + title "[autosetup_version] -- Command Reference" + + section {Introduction} + + p { + See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup' + } + + p { + 'autosetup' provides a number of built-in commands which + are documented below. These may be used from 'auto.def' to test + for features, define variables, create files from templates and + other similar actions. + } + + automf_command_reference + + exit 0 +} + +proc autosetup_output_block {type lines} { + if {[llength $lines]} { + switch $type { + code { + codelines $lines + } + p { + p [join $lines] + } + list { + foreach line $lines { + bullet $line + } + nl + } + } + } +} + +# Generate a command reference from inline documentation +proc automf_command_reference {} { + lappend files $::autosetup(prog) + lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]] + + section "Core Commands" + set type p + set lines {} + set cmd {} + + foreach file $files { + set f [open $file] + while {![eof $f]} { + set line [gets $f] + + # Find lines starting with "# @*" and continuing through the remaining comment lines + if {![regexp {^# @(.*)} $line -> cmd]} { + continue + } + + # Synopsis or command? + if {$cmd eq "synopsis:"} { + section "Module: [file rootname [file tail $file]]" + } else { + subsection $cmd + } + + set lines {} + set type p + + # Now the description + while {![eof $f]} { + set line [gets $f] + + if {![regexp {^#(#)? ?(.*)} $line -> hash cmd]} { + break + } + if {$hash eq "#"} { + set t code + } elseif {[regexp {^- (.*)} $cmd -> cmd]} { + set t list + } else { + set t p + } + + #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd" + + if {$t ne $type || $cmd eq ""} { + # Finish the current block + autosetup_output_block $type $lines + set lines {} + set type $t + } + if {$cmd ne ""} { + lappend lines $cmd + } + } + + autosetup_output_block $type $lines + } + close $f + } +} +} + +# ----- module init ----- + +set modsource(init) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module to help create auto.def and configure + +proc autosetup_init {} { + set create_configure 1 + if {[file exists configure]} { + if {!$::autosetup(force)} { + # Could this be an autosetup configure? + if {![string match "*\nWRAPPER=*" [readfile configure]]} { + puts "I see configure, but not created by autosetup, so I won't overwrite it." + puts "Use autosetup --init --force to overwrite." + set create_configure 0 + } + } else { + puts "I will overwrite the existing configure because you used --force." + } + } else { + puts "I don't see configure, so I will create it." + } + if {$create_configure} { + if {!$::autosetup(installed)} { + user-notice "Warning: Initialising from the development version of autosetup" + + writefile configure "#!/bin/sh\nWRAPPER=\"\$0\" exec $::autosetup(dir)/autosetup \"\$@\"\n" + } else { + writefile configure \ +{#!/bin/sh +dir="`dirname "$0"`/autosetup" +WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" +} + } + catch {exec chmod 755 configure} + } + if {![file exists auto.def]} { + puts "I don't see auto.def, so I will create a default one." + writefile auto.def {# Initial auto.def created by 'autosetup --init' + +use cc + +# Add any user options here +options { +} + +make-config-header config.h +make-template Makefile.in +} + } + if {![file exists Makefile.in]} { + puts "Note: I don't see Makefile.in. You will probably need to create one." + } + + exit 0 +} +} + +# ----- module install ----- + +set modsource(install) { +# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which can install autosetup + +proc autosetup_install {dir} { + if {[catch { + cd $dir + file mkdir autosetup + + set f [open autosetup/autosetup w] + + set publicmodules {} + + # First the main script, but only up until "CUT HERE" + set in [open $::autosetup(dir)/autosetup] + while {[gets $in buf] >= 0} { + if {$buf ne "##-- CUT HERE --##"} { + puts $f $buf + continue + } + + # Insert the static modules here + # i.e. those which don't contain @synopsis: + puts $f "set autosetup(installed) 1" + foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] { + set buf [readfile $file] + if {[string match "*\n# @synopsis:*" $buf]} { + lappend publicmodules $file + continue + } + set modname [file rootname [file tail $file]] + puts $f "# ----- module $modname -----" + puts $f "\nset modsource($modname) \{" + puts $f $buf + puts $f "\}\n" + } + } + close $in + close $f + exec chmod 755 autosetup/autosetup + + # Install public modules + foreach file $publicmodules { + autosetup_install_file $file autosetup + } + + # Install support files + foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} { + autosetup_install_file $::autosetup(dir)/$file autosetup + } + exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh + + writefile autosetup/README.autosetup \ + "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n" + + } error]} { + user-error "Failed to install autosetup: $error" + } + puts "Installed [autosetup_version] to autosetup/" + catch {exec [info nameofexecutable] autosetup/autosetup --init >@stdout 2>@stderr} + + exit 0 +} + +# Append the contents of $file to filehandle $f +proc autosetup_install_append {f file} { + set in [open $file] + puts $f [read $in] + close $in +} + +proc autosetup_install_file {file dir} { + if {![file exists $file]} { + error "Missing installation file '$file'" + } + writefile [file join $dir [file tail $file]] [readfile $file]\n +} + +if {$::autosetup(installed)} { + user-error "autosetup can only be installed from development source, not from installed copy" +} +} + +# ----- module markdown-formatting ----- + +set modsource(markdown-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# markdown format (kramdown syntax) + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " text + regsub -all {([^a-zA-Z])'([^']*)'} $text {\1**`\2`**} text + regsub -all {^'([^']*)'} $text {**`\1`**} text + regsub -all {(http[^ \t\n]*)} $text {[\1](\1)} text + return $text +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc codelines {lines} { + puts "~~~~~~~~~~~~" + foreach line $lines { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc code {text} { + puts "~~~~~~~~~~~~" + foreach line [parse_code_block $text] { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + puts "### `$text`" + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc defn {first args} { + puts "^" + set defn [string trim [join $args \n]] + if {$first ne ""} { + puts "**${first}**" + puts -nonewline ": " + regsub -all "\n\n" $defn "\n: " defn + } + puts "$defn" +} +} + +# ----- module misc ----- + +set modsource(misc) { +# Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module containing misc procs useful to modules +# Largely for platform compatibility + +set autosetup(istcl) [info exists ::tcl_library] +set autosetup(iswin) [string equal windows $tcl_platform(platform)] + +if {$autosetup(iswin)} { + # mingw/windows separates $PATH with semicolons + # and doesn't have an executable bit + proc split-path {} { + split [getenv PATH .] {;} + } + proc file-isexec {exec} { + # Basic test for windows. We ignore .bat + if {[file isfile $exec] || [file isfile $exec.exe]} { + return 1 + } + return 0 + } +} else { + # unix separates $PATH with colons and has and executable bit + proc split-path {} { + split [getenv PATH .] : + } + proc file-isexec {exec} { + file executable $exec + } +} + +# Assume that exec can return stdout and stderr +proc exec-with-stderr {args} { + exec {*}$args 2>@1 +} + +if {$autosetup(istcl)} { + # Tcl doesn't have the env command + proc getenv {name args} { + if {[info exists ::env($name)]} { + return $::env($name) + } + if {[llength $args]} { + return [lindex $args 0] + } + return -code error "environment variable \"$name\" does not exist" + } +} elseif {$autosetup(iswin)} { + # On Windows, backslash convert all environment variables + # (Assume that Tcl does this for us) + proc getenv {name args} { + string map {\\ /} [env $name {*}$args] + } +} else { + # Jim on unix is simple + alias getenv env +} + +# In case 'file normalize' doesn't exist +# +proc file-normalize {path} { + if {[catch {file normalize $path} result]} { + if {$path eq ""} { + return "" + } + set oldpwd [pwd] + if {[file isdir $path]} { + cd $path + set result [pwd] + } else { + cd [file dirname $path] + set result [file join [pwd] [file tail $path]] + } + cd $oldpwd + } + return $result +} + +# If everything is working properly, the only errors which occur +# should be generated in user code (e.g. auto.def). +# By default, we only want to show the error location in user code. +# We use [info frame] to achieve this, but it works differently on Tcl and Jim. +# +# This is designed to be called for incorrect usage in auto.def, via autosetup-error +# +proc error-location {msg} { + if {$::autosetup(debug)} { + return -code error $msg + } + # Search back through the stack trace for the first error in a .def file + for {set i 1} {$i < [info level]} {incr i} { + if {$::autosetup(istcl)} { + array set info [info frame -$i] + } else { + lassign [info frame -$i] info(caller) info(file) info(line) + } + if {[string match *.def $info(file)]} { + return "[relative-path $info(file)]:$info(line): Error: $msg" + } + #puts "Skipping $info(file):$info(line)" + } + return $msg +} + +# Similar to error-location, but called when user code generates an error +# In this case we want to show the stack trace in user code, but not in autosetup code +# (unless --debug is enabled) +# +proc error-stacktrace {msg} { + if {$::autosetup(istcl)} { + if {[regexp {file "([^ ]*)" line ([0-9]*)} $::errorInfo dummy file line]} { + return "[relative-path $file]:$line $msg\n$::errorInfo" + } + return $::errorInfo + } else { + # Prepend a live stacktrace to the error stacktrace, omitting the current level + set stacktrace [concat [info stacktrace] [lrange [stacktrace] 3 end]] + + if {!$::autosetup(debug)} { + # Omit any levels from autosetup or with no file + set newstacktrace {} + foreach {p f l} $stacktrace { + if {[string match "*autosetup" $f] || $f eq ""} { + #puts "Skipping $p $f:$l" + continue + } + lappend newstacktrace $p $f $l + } + set stacktrace $newstacktrace + } + + # Convert filenames to relative paths + set newstacktrace {} + foreach {p f l} $stacktrace { + lappend newstacktrace $p [relative-path $f] $l + } + lassign $newstacktrace p f l + if {$f ne ""} { + set prefix "$f:$l: " + } else { + set prefix "" + } + + return "${prefix}Error: $msg\n[stackdump $newstacktrace]" + } +} +} + +# ----- module text-formatting ----- + +set modsource(text-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting + +use formatting + +proc wordwrap {text length {firstprefix ""} {nextprefix ""}} { + set len 0 + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + + # Use man-page conventions for highlighting 'quoted' and *quoted* + # single words. + # Use x^Hx for *bold* and _^Hx for 'underline'. + # + # less and more will both understand this. + # Pipe through 'col -b' to remove them. + if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "_\b&" word + append word $dot + } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "&\b&" word + append word $dot + } + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} +proc title {text} { + underline [string trim $text] = + nl +} +proc p {text} { + wordwrap $text 80 + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[string trim $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + wordwrap $text 76 " * " " " +} +proc indent {text} { + wordwrap $text 76 " " " " +} +proc defn {first args} { + if {$first ne ""} { + underline " $first" ~ + } + foreach p $args { + if {$p ne ""} { + indent $p + } + } +} +} + +# ----- module wiki-formatting ----- + +set modsource(wiki-formatting) { +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# wiki.tcl.tk format output + +use formatting + +proc joinlines {text} { + set lines {} + foreach l [split [string trim $text] \n] { + lappend lines [string trim $l] + } + join $lines +} +proc p {text} { + puts [joinlines $text] + puts "" +} +proc title {text} { + puts "*** [joinlines $text] ***" + puts "" +} +proc codelines {lines} { + puts "======" + foreach line $lines { + puts " $line" + } + puts "======" +} +proc code {text} { + puts "======" + foreach line [parse_code_block $text] { + puts " $line" + } + puts "======" +} +proc nl {} { +} +proc section {text} { + puts "'''$text'''" + puts "" +} +proc subsection {text} { + puts "''$text''" + puts "" +} +proc bullet {text} { + puts " * [joinlines $text]" +} +proc indent {text} { + puts " : [joinlines $text]" +} +proc defn {first args} { + if {$first ne ""} { + indent '''$first''' + } + + foreach p $args { + p $p + } +} +} + + +################################################################## +# +# Entry/Exit +# +if {$autosetup(debug)} { + main $argv +} +if {[catch {main $argv} msg] == 1} { + show-notices + puts stderr [error-stacktrace $msg] + if {!$autosetup(debug) && !$autosetup(istcl)} { + puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace" + } + exit 1 +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl new file mode 100755 index 0000000..e8e5e86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-lib.tcl @@ -0,0 +1,77 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# Provides a library of common tests on top of the 'cc' module. + +use cc + +module-options {} + +# @cc-check-lfs +# +# The equivalent of the AC_SYS_LARGEFILE macro +# +# defines 'HAVE_LFS' if LFS is available, +# and defines '_FILE_OFFSET_BITS=64' if necessary +# +# Returns 1 if 'LFS' is available or 0 otherwise +# +proc cc-check-lfs {} { + cc-check-includes sys/types.h + msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..." + set lfs 1 + if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} { + msg-result no + } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} { + define _FILE_OFFSET_BITS 64 + msg-result yes + } else { + set lfs 0 + msg-result none + } + define-feature lfs $lfs + return $lfs +} + +# @cc-check-endian +# +# The equivalent of the AC_C_BIGENDIAN macro +# +# defines 'HAVE_BIG_ENDIAN' if endian is known to be big, +# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little. +# +# Returns 1 if determined, or 0 if not. +# +proc cc-check-endian {} { + cc-check-includes sys/types.h sys/param.h + set rc 0 + msg-checking "Checking endian..." + cc-with {-includes {sys/types.h sys/param.h}} { + if {[cctest -code { + #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != BIG_ENDIAN + #error little + #endif + }]} { + define-feature big-endian + msg-result "big" + set rc 1 + } elseif {[cctest -code { + #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != LITTLE_ENDIAN + #error big + #endif + }]} { + define-feature little-endian + msg-result "little" + set rc 1 + } else { + msg-result "unknown" + } + } + return $rc +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl new file mode 100755 index 0000000..1e77440 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc-shared.tcl @@ -0,0 +1,63 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-shared' module provides support for shared libraries and shared objects. +# It defines the following variables: +# +## SH_CFLAGS Flags to use compiling sources destined for a shared library +## SH_LDFLAGS Flags to use linking a shared library +## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object +## SHOBJ_LDFLAGS Flags to use linking a shared object +## SH_LINKFLAGS Flags to use linking an executable which will load shared objects +## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries + +module-options {} + +foreach i {SH_LINKFLAGS SH_CFLAGS SH_LDFLAGS SHOBJ_CFLAGS SHOBJ_LDFLAGS} { + define $i "" +} + +define LD_LIBRARY_PATH LD_LIBRARY_PATH + +switch -glob -- [get-define host] { + *-*-darwin* { + define SH_CFLAGS -dynamic + define SH_LDFLAGS "-dynamiclib" + define SHOBJ_CFLAGS "-dynamic -fno-common" + define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup" + define LD_LIBRARY_PATH DYLD_LIBRARY_PATH + } + *-*-ming* { + define SH_LDFLAGS -shared + define SHOBJ_LDFLAGS -shared + } + *-*-cygwin { + define SH_LDFLAGS -shared + define SHOBJ_LDFLAGS -shared + } + *-*-solaris* { + # XXX: These haven't been fully tested. + #define SH_LINKFLAGS -Wl,-export-dynamic + define SH_CFLAGS -Kpic + define SHOBJ_CFLAGS -Kpic + define SHOBJ_LDFLAGS "-G" + } + *-*-hpux { + # XXX: These haven't been tested + define SH_LINKFLAGS -Wl,+s + define SH_CFLAGS +z + define SHOBJ_CFLAGS "+O3 +z" + define SHOBJ_LDFLAGS -b + define LD_LIBRARY_PATH SHLIB_PATH + } + * { + # Generic Unix settings + define SH_LINKFLAGS -rdynamic + define SH_CFLAGS -fpic + define SH_LDFLAGS -shared + define SHOBJ_CFLAGS -fpic + define SHOBJ_LDFLAGS "-shared" + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl new file mode 100755 index 0000000..707e69c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/cc.tcl @@ -0,0 +1,660 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc' module supports checking various 'features' of the C or C++ +# compiler/linker environment. Common commands are cc-check-includes, +# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template. +# +# The following environment variables are used if set: +# +## CC - C compiler +## CXX - C++ compiler +## CCACHE - Set to "none" to disable automatic use of ccache +## CFLAGS - Additional C compiler flags +## CXXFLAGS - Additional C++ compiler flags +## LDFLAGS - Additional compiler flags during linking +## LIBS - Additional libraries to use (for all tests) +## CROSS - Tool prefix for cross compilation +# +# The following variables are defined from the corresponding +# environment variables if set. +# +## CPPFLAGS +## LINKFLAGS +## CC_FOR_BUILD +## LD + +use system + +module-options {} + +# Note that the return code is not meaningful +proc cc-check-something {name code} { + uplevel 1 $code +} + +# Checks for the existence of the given function by linking +# +proc cctest_function {function} { + cctest -link 1 -declare "extern void $function\(void);" -code "$function\();" +} + +# Checks for the existence of the given type by compiling +proc cctest_type {type} { + cctest -code "$type _x;" +} + +# Checks for the existence of the given type/structure member. +# e.g. "struct stat.st_mtime" +proc cctest_member {struct_member} { + lassign [split $struct_member .] struct member + cctest -code "static $struct _s; return sizeof(_s.$member);" +} + +# Checks for the existence of the given define by compiling +# +proc cctest_define {name} { + cctest -code "#ifndef $name\n#error not defined\n#endif" +} + +# Checks for the existence of the given name either as +# a macro (#define) or an rvalue (such as an enum) +# +proc cctest_decl {name} { + cctest -code "#ifndef $name\n(void)$name;\n#endif" +} + +# @cc-check-sizeof type ... +# +# Checks the size of the given types (between 1 and 32, inclusive). +# Defines a variable with the size determined, or "unknown" otherwise. +# e.g. for type 'long long', defines SIZEOF_LONG_LONG. +# Returns the size of the last type. +# +proc cc-check-sizeof {args} { + foreach type $args { + msg-checking "Checking for sizeof $type..." + set size unknown + # Try the most common sizes first + foreach i {4 8 1 2 16 32} { + if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} { + set size $i + break + } + } + msg-result $size + set define [feature-define-name $type SIZEOF_] + define $define $size + } + # Return the last result + get-define $define +} + +# Checks for each feature in $list by using the given script. +# +# When the script is evaluated, $each is set to the feature +# being checked, and $extra is set to any additional cctest args. +# +# Returns 1 if all features were found, or 0 otherwise. +proc cc-check-some-feature {list script} { + set ret 1 + foreach each $list { + if {![check-feature $each $script]} { + set ret 0 + } + } + return $ret +} + +# @cc-check-includes includes ... +# +# Checks that the given include files can be used +proc cc-check-includes {args} { + cc-check-some-feature $args { + cctest -includes $each + } +} + +# @cc-check-types type ... +# +# Checks that the types exist. +proc cc-check-types {args} { + cc-check-some-feature $args { + cctest_type $each + } +} + +# @cc-check-defines define ... +# +# Checks that the given preprocessor symbol is defined +proc cc-check-defines {args} { + cc-check-some-feature $args { + cctest_define $each + } +} + +# @cc-check-decls name ... +# +# Checks that each given name is either a preprocessor symbol or rvalue +# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx +# rather than HAVE_xxx +proc cc-check-decls {args} { + set ret 1 + foreach name $args { + msg-checking "Checking for $name..." + set r [cctest_decl $name] + define-feature "decl $name" $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + set ret 0 + } + } + return $ret +} + +# @cc-check-functions function ... +# +# Checks that the given functions exist (can be linked) +proc cc-check-functions {args} { + cc-check-some-feature $args { + cctest_function $each + } +} + +# @cc-check-members type.member ... +# +# Checks that the given type/structure members exist. +# A structure member is of the form "struct stat.st_mtime" +proc cc-check-members {args} { + cc-check-some-feature $args { + cctest_member $each + } +} + +# @cc-check-function-in-lib function libs ?otherlibs? +# +# Checks that the given given function can be found in one of the libs. +# +# First checks for no library required, then checks each of the libraries +# in turn. +# +# If the function is found, the feature is defined and lib_$function is defined +# to -l$lib where the function was found, or "" if no library required. +# In addition, -l$lib is added to the LIBS define. +# +# If additional libraries may be needed for linking, they should be specified +# as $extralibs as "-lotherlib1 -lotherlib2". +# These libraries are not automatically added to LIBS. +# +# Returns 1 if found or 0 if not. +# +proc cc-check-function-in-lib {function libs {otherlibs {}}} { + msg-checking "Checking libs for $function..." + set found 0 + cc-with [list -libs $otherlibs] { + if {[cctest_function $function]} { + msg-result "none needed" + define lib_$function "" + incr found + } else { + foreach lib $libs { + cc-with [list -libs -l$lib] { + if {[cctest_function $function]} { + msg-result -l$lib + define lib_$function -l$lib + define-append LIBS -l$lib + incr found + break + } + } + } + } + } + if {$found} { + define [feature-define-name $function] + } else { + msg-result "no" + } + return $found +} + +# @cc-check-tools tool ... +# +# Checks for existence of the given compiler tools, taking +# into account any cross compilation prefix. +# +# For example, when checking for "ar", first AR is checked on the command +# line and then in the environment. If not found, "${host}-ar" or +# simply "ar" is assumed depending upon whether cross compiling. +# The path is searched for this executable, and if found AR is defined +# to the executable name. +# +# It is an error if the executable is not found. +# +proc cc-check-tools {args} { + foreach tool $args { + set TOOL [string toupper $tool] + set exe [get-env $TOOL [get-define cross]$tool] + if {![find-executable $exe]} { + user-error "Failed to find $exe" + } + define $TOOL $exe + } +} + +# @cc-check-progs prog ... +# +# Checks for existence of the given executables on the path. +# +# For example, when checking for "grep", the path is searched for +# the executable, 'grep', and if found GREP is defined as "grep". +# +# It the executable is not found, the variable is defined as false. +# Returns 1 if all programs were found, or 0 otherwise. +# +proc cc-check-progs {args} { + set failed 0 + foreach prog $args { + set PROG [string toupper $prog] + msg-checking "Checking for $prog..." + if {![find-executable $prog]} { + msg-result no + define $PROG false + incr failed + } else { + msg-result ok + define $PROG $prog + } + } + expr {!$failed} +} + +# Adds the given settings to $::autosetup(ccsettings) and +# returns the old settings. +# +proc cc-add-settings {settings} { + if {[llength $settings] % 2} { + autosetup-error "settings list is missing a value: $settings" + } + + set prev [cc-get-settings] + # workaround a bug in some versions of jimsh by forcing + # conversion of $prev to a list + llength $prev + + array set new $prev + + foreach {name value} $settings { + switch -exact -- $name { + -cflags - -includes { + # These are given as lists + lappend new($name) {*}$value + } + -declare { + lappend new($name) $value + } + -libs { + # Note that new libraries are added before previous libraries + set new($name) [list {*}$value {*}$new($name)] + } + -link - -lang { + set new($name) $value + } + -source - -sourcefile - -code { + # XXX: These probably are only valid directly from cctest + set new($name) $value + } + default { + autosetup-error "unknown cctest setting: $name" + } + } + } + + cc-store-settings [array get new] + + return $prev +} + +proc cc-store-settings {new} { + set ::autosetup(ccsettings) $new +} + +proc cc-get-settings {} { + return $::autosetup(ccsettings) +} + +# Similar to cc-add-settings, but each given setting +# simply replaces the existing value. +# +# Returns the previous settings +proc cc-update-settings {args} { + set prev [cc-get-settings] + cc-store-settings [dict merge $prev $args] + return $prev +} + +# @cc-with settings ?{ script }? +# +# Sets the given 'cctest' settings and then runs the tests in 'script'. +# Note that settings such as -lang replace the current setting, while +# those such as -includes are appended to the existing setting. +# +# If no script is given, the settings become the default for the remainder +# of the auto.def file. +# +## cc-with {-lang c++} { +## # This will check with the C++ compiler +## cc-check-types bool +## cc-with {-includes signal.h} { +## # This will check with the C++ compiler, signal.h and any existing includes. +## ... +## } +## # back to just the C++ compiler +## } +# +# The -libs setting is special in that newer values are added *before* earlier ones. +# +## cc-with {-libs {-lc -lm}} { +## cc-with {-libs -ldl} { +## cctest -libs -lsocket ... +## # libs will be in this order: -lsocket -ldl -lc -lm +## } +## } +proc cc-with {settings args} { + if {[llength $args] == 0} { + cc-add-settings $settings + } elseif {[llength $args] > 1} { + autosetup-error "usage: cc-with settings ?script?" + } else { + set save [cc-add-settings $settings] + set rc [catch {uplevel 1 [lindex $args 0]} result info] + cc-store-settings $save + if {$rc != 0} { + return $result -code [dict get $info -code] + } + return $result + } +} + +# @cctest ?settings? +# +# Low level C compiler checker. Compiles and or links a small C program +# according to the arguments and returns 1 if OK, or 0 if not. +# +# Supported settings are: +# +## -cflags cflags A list of flags to pass to the compiler +## -includes list A list of includes, e.g. {stdlib.h stdio.h} +## -declare code Code to declare before main() +## -link 1 Don't just compile, link too +## -lang c|c++ Use the C (default) or C++ compiler +## -libs liblist List of libraries to link, e.g. {-ldl -lm} +## -code code Code to compile in the body of main() +## -source code Compile a complete program. Ignore -includes, -declare and -code +## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] +# +# Unless -source or -sourcefile is specified, the C program looks like: +# +## #include <firstinclude> /* same for remaining includes in the list */ +## +## declare-code /* any code in -declare, verbatim */ +## +## int main(void) { +## code /* any code in -code, verbatim */ +## return 0; +## } +# +# Any failures are recorded in 'config.log' +# +proc cctest {args} { + set src conftest__.c + set tmp conftest__ + + # Easiest way to merge in the settings + cc-with $args { + array set opts [cc-get-settings] + } + + if {[info exists opts(-sourcefile)]} { + set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] + } + if {[info exists opts(-source)]} { + set lines $opts(-source) + } else { + foreach i $opts(-includes) { + if {$opts(-code) ne "" && ![feature-checked $i]} { + # Compiling real code with an unchecked header file + # Quickly (and silently) check for it now + + # Remove all -includes from settings before checking + set saveopts [cc-update-settings -includes {}] + msg-quiet cc-check-includes $i + cc-store-settings $saveopts + } + if {$opts(-code) eq "" || [have-feature $i]} { + lappend source "#include <$i>" + } + } + lappend source {*}$opts(-declare) + lappend source "int main(void) {" + lappend source $opts(-code) + lappend source "return 0;" + lappend source "}" + + set lines [join $source \n] + } + + # Build the command line + set cmdline {} + lappend cmdline {*}[get-define CCACHE] + switch -exact -- $opts(-lang) { + c++ { + lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] + } + c { + lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] + } + default { + autosetup-error "cctest called with unknown language: $opts(-lang)" + } + } + + if {!$opts(-link)} { + set tmp conftest__.o + lappend cmdline -c + } + lappend cmdline {*}$opts(-cflags) + + switch -glob -- [get-define host] { + *-*-darwin* { + # Don't generate .dSYM directories + lappend cmdline -gstabs + } + } + lappend cmdline $src -o $tmp {*}$opts(-libs) + + # At this point we have the complete command line and the + # complete source to be compiled. Get the result from cache if + # we can + if {[info exists ::cc_cache($cmdline,$lines)]} { + msg-checking "(cached) " + set ok $::cc_cache($cmdline,$lines) + if {$::autosetup(debug)} { + configlog "From cache (ok=$ok): [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + return $ok + } + + writefile $src $lines\n + + set ok 1 + if {[catch {exec-with-stderr {*}$cmdline} result errinfo]} { + configlog "Failed: [join $cmdline]" + configlog $result + configlog "============" + configlog "The failed code was:" + configlog $lines + configlog "============" + set ok 0 + } elseif {$::autosetup(debug)} { + configlog "Compiled OK: [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + file delete $src + file delete $tmp + + # cache it + set ::cc_cache($cmdline,$lines) $ok + + return $ok +} + +# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*? +# +# Deprecated - see make-config-header +proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} { + user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead" + make-config-header $file -auto $autopatterns -bare $barepatterns +} + +# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ... +# +# Examines all defined variables which match the given patterns +# and writes an include file, $file, which defines each of these. +# Variables which match '-auto' are output as follows: +# - defines which have the value "0" are ignored. +# - defines which have integer values are defined as the integer value. +# - any other value is defined as a string, e.g. "value" +# Variables which match '-bare' are defined as-is. +# Variables which match '-str' are defined as a string, e.g. "value" +# Variables which match '-none' are omitted. +# +# Note that order is important. The first pattern which matches is selected +# Default behaviour is: +# +# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none * +# +# If the file would be unchanged, it is not written. +proc make-config-header {file args} { + set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]] + file mkdir [file dirname $file] + set lines {} + lappend lines "#ifndef $guard" + lappend lines "#define $guard" + + # Add some defaults + lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* + + foreach n [lsort [dict keys [all-defines]]] { + set value [get-define $n] + set type [calc-define-output-type $n $args] + switch -exact -- $type { + -bare { + # Just output the value unchanged + } + -none { + continue + } + -str { + set value \"$value\" + } + -auto { + # Automatically determine the type + if {$value eq "0"} { + lappend lines "/* #undef $n */" + continue + } + if {![string is integer -strict $value]} { + set value \"$value\" + } + } + "" { + continue + } + default { + autosetup-error "Unknown type in make-config-header: $type" + } + } + lappend lines "#define $n $value" + } + lappend lines "#endif" + set buf [join $lines \n] + write-if-changed $file $buf { + msg-result "Created $file" + } +} + +proc calc-define-output-type {name spec} { + foreach {type patterns} $spec { + foreach pattern $patterns { + if {[string match $pattern $name]} { + return $type + } + } + } + return "" +} + +# Initialise some values from the environment or commandline or default settings +foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} { + lassign $i var default + define $var [get-env $var $default] +} + +if {[env-is-set CC]} { + # Set by the user, so don't try anything else + set try [list [get-env CC ""]] +} else { + # Try some reasonable options + set try [list [get-define cross]cc [get-define cross]gcc] +} +define CC [find-an-executable {*}$try] +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CPP [get-env CPP "[get-define CC] -E"] + +# XXX: Could avoid looking for a C++ compiler until requested +# Note that if CXX isn't found, we just set it to "false". It might not be needed. +if {[env-is-set CXX]} { + define CXX [find-an-executable -required [get-env CXX ""]] +} else { + define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++ false] +} + +# CXXFLAGS default to CFLAGS if not specified +define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]] + +cc-check-tools ld + +# May need a CC_FOR_BUILD, so look for one +define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false] + +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CCACHE [find-an-executable [get-env CCACHE ccache]] + +# Initial cctest settings +cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {}} + +msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]" +if {[get-define CXX] ne "false"} { + msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]" +} +msg-result "Build C compiler...[get-define CC_FOR_BUILD]" + +if {![cc-check-includes stdlib.h]} { + user-error "Compiler does not work. See config.log" +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess new file mode 100755 index 0000000..4c8f032 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.guess @@ -0,0 +1,1508 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to <config-patches@gnu.org> and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' HUP INT TERM + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" HUP INT PIPE TERM ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-tilera-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +and + http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub new file mode 100755 index 0000000..320e303 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/config.sub @@ -0,0 +1,1739 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile-* | tilegx-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh new file mode 100755 index 0000000..7ef152a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/find-tclsh @@ -0,0 +1,17 @@ +#!/bin/sh +# Looks for a suitable tclsh or jimsh in the PATH +# If not found, builds a bootstrap jimsh from source +d=`dirname "$0"` +{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0 +PATH="$PATH:$d" +for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do + { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0 +done +echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" +./make-bootstrap-jim > $d/jimsh0.c +for cc in ${CC_FOR_BUILD:-cc} gcc; do + { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue + "$d/jimsh0" "$d/test-tclsh" && exit 0 +done +echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." +echo false diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl new file mode 100755 index 0000000..f05d05b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/system.tcl @@ -0,0 +1,268 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# This module supports common system interrogation and options +# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEXT. +# +# It also support the 'feature' naming convention, where searching +# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H +# +module-options { + host:host-alias => {a complete or partial cpu-vendor-opsys for the system where + the application will run (defaults to the same value as --build)} + build:build-alias => {a complete or partial cpu-vendor-opsys for the system + where the application will be built (defaults to the + result of running config.guess)} + prefix:dir => {the target directory for the build (defaults to /usr/local)} + + # These (hidden) options are supported for autoconf/automake compatibility + exec-prefix: + bindir: + sbindir: + includedir: + mandir: + infodir: + libexecdir: + datadir: + libdir: + sysconfdir: + sharedstatedir: + localstatedir: + maintainer-mode=0 + dependency-tracking=0 +} + +# Returns 1 if exists, or 0 if not +# +proc check-feature {name code} { + msg-checking "Checking for $name..." + set r [uplevel 1 $code] + define-feature $name $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + } + return $r +} + +# @have-feature name ?default=0? +# +# Returns the value of the feature if defined, or $default if not. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc have-feature {name {default 0}} { + get-define [feature-define-name $name] $default +} + +# @define-feature name ?value=1? +# +# Sets the feature 'define' to the given value. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc define-feature {name {value 1}} { + define [feature-define-name $name] $value +} + +# @feature-checked name +# +# Returns 1 if the feature has been checked, whether true or not +# +proc feature-checked {name} { + is-defined [feature-define-name $name] +} + +# @feature-define-name name ?prefix=HAVE_? +# +# Converts a name to the corresponding define, +# e.g. sys/stat.h becomes HAVE_SYS_STAT_H. +# +# Converts * to P and all non-alphanumeric to underscore. +# +proc feature-define-name {name {prefix HAVE_}} { + string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _] +} + +# If $file doesn't exist, or it's contents are different than $buf, +# the file is written and $script is executed. +# Otherwise a "file is unchanged" message is displayed. +proc write-if-changed {file buf {script {}}} { + set old [readfile $file ""] + if {$old eq $buf && [file exists $file]} { + msg-result "$file is unchanged" + } else { + writefile $file $buf\n + uplevel 1 $script + } +} + +# @make-template template ?outfile? +# +# Reads the input file <srcdir>/$template and writes the output file $outfile. +# If $outfile is blank/omitted, $template should end with ".in" which +# is removed to create the output file name. +# +# Each pattern of the form @define@ is replaced the the corresponding +# define, if it exists, or left unchanged if not. +# +# The special value @srcdir@ is subsituted with the relative +# path to the source directory from the directory where the output +# file is created. Use @top_srcdir@ for the absolute path. +# +# Conditional sections may be specified as follows: +## @if name == value +## lines +## @else +## lines +## @endif +# +# Where 'name' is a defined variable name and @else is optional. +# If the expression does not match, all lines through '@endif' are ignored. +# +# The alternative forms may also be used: +## @if name +## @if name != value +# +# Where the first form is true if the variable is defined, but not empty or 0 +# +# Currently these expressions can't be nested. +# +proc make-template {template {out {}}} { + set infile [file join $::autosetup(srcdir) $template] + + if {![file exists $infile]} { + user-error "Template $template is missing" + } + + # Define this as late as possible + define AUTODEPS $::autosetup(deps) + + if {$out eq ""} { + if {[file ext $template] ne ".in"} { + autosetup-error "make_template $template has no target file and can't guess" + } + set out [file rootname $template] + } + + set outdir [file dirname $out] + + # Make sure the directory exists + file mkdir $outdir + + # Set up srcdir to be relative to the target dir + define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] + + set mapping {} + foreach {n v} [array get ::define] { + lappend mapping @$n@ $v + } + set result {} + foreach line [split [readfile $infile] \n] { + if {[info exists cond]} { + set l [string trimright $line] + if {$l eq "@endif"} { + unset cond + continue + } + if {$l eq "@else"} { + set cond [expr {!$cond}] + continue + } + if {$cond} { + lappend result $line + } + continue + } + if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} { + lassign $expression equal value + set varval [get-define $name ""] + if {$equal eq ""} { + set cond [expr {$varval ni {"" 0}}] + } else { + set cond [expr {$varval eq $value}] + if {$equal ne "=="} { + set cond [expr {!$cond}] + } + } + continue + } + lappend result $line + } + writefile $out [string map $mapping [join $result \n]]\n + + msg-result "Created [relative-path $out] from [relative-path $template]" +} + +# build/host tuples and cross-compilation prefix +set build [opt-val build] +define build_alias $build +if {$build eq ""} { + define build [config_guess] +} else { + define build [config_sub $build] +} + +set host [opt-val host] +define host_alias $host +if {$host eq ""} { + define host [get-define build] + set cross "" +} else { + define host [config_sub $host] + set cross $host- +} +define cross [get-env CROSS $cross] + +set prefix [opt-val prefix /usr/local] + +# These are for compatibility with autoconf +define target [get-define host] +define prefix $prefix +define builddir $autosetup(builddir) +define srcdir $autosetup(srcdir) +# Allow this to come from the environment +define top_srcdir [get-env top_srcdir [get-define srcdir]] + +# autoconf supports all of these +set exec_prefix [opt-val exec-prefix $prefix] +define exec_prefix $exec_prefix +foreach {name defpath} { + bindir /bin + sbindir /sbin + libexecdir /libexec + libdir /lib +} { + define $name [opt-val $name $exec_prefix$defpath] +} +foreach {name defpath} { + datadir /share + sysconfdir /etc + sharedstatedir /com + localstatedir /var + infodir /share/info + mandir /share/man + includedir /include +} { + define $name [opt-val $name $prefix$defpath] +} + +define SHELL [get-env SHELL [find-an-executable sh bash ksh]] + +# Windows vs. non-Windows +switch -glob -- [get-define host] { + *-*-ming* - *-*-cygwin { + define-feature windows + define EXEEXT .exe + } + default { + define EXEEXT "" + } +} + +# Display +msg-result "Host System...[get-define host]" +msg-result "Build System...[get-define build]" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh new file mode 100755 index 0000000..75126d2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/autosetup/test-tclsh @@ -0,0 +1,20 @@ +# A small Tcl script to verify that the chosen +# interpreter works. Sometimes we might e.g. pick up +# an interpreter for a different arch. +# Outputs the full path to the interpreter + +if {[catch {info version} version] == 0} { + # This is Jim Tcl + if {$version >= 0.72} { + # Ensure that regexp works + regexp (a.*?) a + puts [info nameofexecutable] + exit 0 + } +} elseif {[catch {info tclversion} version] == 0} { + if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} { + puts [info nameofexecutable] + exit 0 + } +} +exit 1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl new file mode 100755 index 0000000..e7adf4b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/bootstrap.tcl @@ -0,0 +1,3 @@ +# No need for package support in the bootstrap jimsh, but +# Tcl extensions call package require +proc package {args} {} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure new file mode 100755 index 0000000..1c5586f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure @@ -0,0 +1,3 @@ +#!/bin/sh +dir="`dirname "$0"`/autosetup" +WRAPPER="$0" exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure.ac b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure.ac new file mode 100755 index 0000000..b70b5d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/configure.ac @@ -0,0 +1 @@ +# Dummy configure.ac to make automake happy diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt new file mode 100755 index 0000000..8dbfcfc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/andrew.txt @@ -0,0 +1,65 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs86142ang; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Received: by 10.142.238.12 with SMTP id l12mr5009290wfh.204.1216194359186; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Return-Path: <andrew@lunn.ch> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 31si6762736wff.16.2008.07.16.00.45.57; + Wed, 16 Jul 2008 00:45:59 -0700 (PDT) +Received-SPF: fail (google.com: domain of andrew@lunn.ch does not designate 209.85.100.29 as permitted sender) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=hardfail (google.com: domain of andrew@lunn.ch does not designate 209.85.100.29 as permitted sender) smtp.mail=andrew@lunn.ch +Received: from londo.lunn.ch ([80.238.139.98]:48839 ident=mail) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <andrew@lunn.ch>) + id 1KJ1ht-00085G-Ng + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 09:45:52 +0200 +Received: from lunn by londo.lunn.ch with local (Exim 3.36 #1 (Debian)) + id 1KJ1hq-0005ss-00; Wed, 16 Jul 2008 09:45:46 +0200 +Date: Wed, 16 Jul 2008 09:45:46 +0200 +From: Andrew Lunn <andrew@lunn.ch> +To: ?yvind Harboe <oyvind.harboe@zylin.com> +Cc: jim-devel@lists.berlios.de, antirez@gmail.com, patthoyts@users.sf.net, + andrew@lunn.ch, openocd@duaneellis.com, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +Subject: Re: Change Jim Tcl license +Message-ID: <20080716074546.GC24771@lunn.ch> +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Disposition: inline +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +User-Agent: Mutt/1.5.18 (2008-05-17) +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - lunn.ch +X-Source: +X-Source-Args: +X-Source-Dir: + +On Wed, Jul 16, 2008 at 09:34:14AM +0200, ?yvind Harboe wrote: +> Hi all, +> +> I'm currently the maintainer of Jim Tcl trying as best as I can +> to fill Salvatore's shoes. +> +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. + +I've no problems with this, but my contributions are very minimal. + +Do you want this written down, in blood, to keep the lawyers happy? + +At a minimum i think everybody's agreement needs to be posted to a +public email list which is publicly archived etc so there is a +record of the agreement... + + Andrew diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt new file mode 100755 index 0000000..806f7ed --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/clemens.txt @@ -0,0 +1,87 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs114742ang; + Wed, 16 Jul 2008 08:58:18 -0700 (PDT) +Received: by 10.114.137.2 with SMTP id k2mr325372wad.95.1216223896673; + Wed, 16 Jul 2008 08:58:16 -0700 (PDT) +Return-Path: <ml-jim@qiao.in-berlin.de> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id m28si10145125waf.16.2008.07.16.08.58.15; + Wed, 16 Jul 2008 08:58:16 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of ml-jim@qiao.in-berlin.de) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of ml-jim@qiao.in-berlin.de) smtp.mail=ml-jim@qiao.in-berlin.de +Received: from gnu.in-berlin.de ([192.109.42.4]:58401) + by cpanel5.proisp.no with esmtps (TLSv1:AES256-SHA:256) + (Exim 4.69) + (envelope-from <ml-jim@qiao.in-berlin.de>) + id 1KJ9OG-0006Hf-8y + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 17:58:07 +0200 +X-Envelope-From: ml-jim@qiao.in-berlin.de +X-Envelope-To: <oyvind.harboe@zylin.com> +Received: from qiao.in-berlin.de (qiao.in-berlin.de [217.197.85.72]) + by gnu.in-berlin.de (8.13.8/8.13.8/Debian-2) with ESMTP id m6GFvxio009504 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 17:58:02 +0200 +Received: from [192.168.0.10] ([::ffff:192.168.0.10]) + by qiao.in-berlin.de with esmtp; Wed, 16 Jul 2008 18:00:04 +0200 + id 0001D68D.487E1B04.000042E7 +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Mime-Version: 1.0 (Apple Message framework v753.1) +Content-Type: text/plain; charset=ISO-8859-1; delsp=yes; format=flowed +Message-Id: <E112D7A6-89D1-40C8-913C-7DAF7303E7EC@qiao.in-berlin.de> +Cc: jim-devel@lists.berlios.de, antirez@gmail.com, patthoyts@users.sf.net, + andrew@lunn.ch, openocd@duaneellis.com, uklein@klein-messgeraete.de +Content-Transfer-Encoding: quoted-printable +From: Clemens Hintze <ml-jim@qiao.in-berlin.de> +Subject: Re: Change Jim Tcl license +Date: Wed, 16 Jul 2008 17:58:14 +0200 +To: "=?ISO-8859-1?Q?\"=D8yvind_Harboe\"?=" <oyvind.harboe@zylin.com> +X-Mailer: Apple Mail (2.753.1) +X-Spam-Score: (0.101) BAYES_50,RDNS_NONE +X-Scanned-By: MIMEDefang_at_IN-Berlin_e.V. on 192.109.42.4 +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - qiao.in-berlin.de +X-Source: +X-Source-Args: +X-Source-Dir: + + +Am 16.07.2008 um 09:34 schrieb =D8yvind Harboe: + +> Hi all, + +Hi =D8yvind, + +(...) + +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. + +No problem with me: I agree to permit my contributions to the Jim =20 +project to be +re-licensed under a BSD compatible license. + +(...) + +> Please let me know if any of the emails below are wrong(chi is +> missing) or the list is not complete. + +After consultation with the voices in my head, I can ensure you, =20 +'chi' is also agreeing with the re-licensing, because its me too ;-) + +Thank you very much to revive Jim! :-) + +Best regards, +Clemens Hintze. + +(...)= diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt new file mode 100755 index 0000000..56f962c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/duane.txt @@ -0,0 +1,65 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs93801ang; + Wed, 16 Jul 2008 03:40:02 -0700 (PDT) +Received: by 10.142.148.10 with SMTP id v10mr5070849wfd.317.1216204801306; + Wed, 16 Jul 2008 03:40:01 -0700 (PDT) +Return-Path: <openocd@duaneellis.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 27si9313433wff.3.2008.07.16.03.40.00; + Wed, 16 Jul 2008 03:40:01 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of openocd@duaneellis.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of openocd@duaneellis.com) smtp.mail=openocd@duaneellis.com +Received: from smtpout10-04.prod.mesa1.secureserver.net ([64.202.165.238]:48803 helo=smtpout10.prod.mesa1.secureserver.net) + by cpanel5.proisp.no with smtp (Exim 4.69) + (envelope-from <openocd@duaneellis.com>) + id 1KJ4QL-0005cq-GB + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 12:39:54 +0200 +Received: (qmail 2305 invoked from network); 16 Jul 2008 10:39:56 -0000 +Received: from unknown (68.37.53.103) + by smtpout10-04.prod.mesa1.secureserver.net (64.202.165.238) with ESMTP; 16 Jul 2008 10:39:55 -0000 +Message-ID: <487DCFEC.4010104@duaneellis.com> +Date: Wed, 16 Jul 2008 06:39:40 -0400 +From: Duane Ellis <openocd@duaneellis.com> +Reply-To: openocd@duaneellis.com +User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) +MIME-Version: 1.0 +To: =?ISO-8859-1?Q?=D8yvind_Harboe?= <oyvind.harboe@zylin.com> +CC: jim-devel@lists.berlios.de, antirez@gmail.com, + patthoyts@users.sf.net, andrew@lunn.ch, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +Subject: Re: Change Jim Tcl license +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 8bit +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - duaneellis.com +X-Source: +X-Source-Args: +X-Source-Dir: + +Oyvind Harboe wrote: +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. +> +> +OK - from me + + --Duane. + +-Duane. + + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt new file mode 100755 index 0000000..af4a8e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/oharboe.txt @@ -0,0 +1,85 @@ + +Received: by 10.100.7.20 with HTTP; Wed, 16 Jul 2008 10:12:05 -0700 (PDT) +Message-ID: <c09652430807161012m178c5fbesef9a3f831e4d1dac@mail.gmail.com> +Date: Wed, 16 Jul 2008 19:12:05 +0200 +From: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Sender: oyvindharboe@gmail.com +To: jim-devel@lists.berlios.de +Subject: Re: Change Jim Tcl license +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Delivered-To: oyvindharboe@gmail.com +X-Google-Sender-Auth: fc18e85532eee8f2 + +For the record: + +I would like my contributions to Jim Tcl to be under a FreeBSD license too= +. + +On Wed, Jul 16, 2008 at 9:34 AM, =D8yvind Harboe <oyvind.harboe@zylin.com> = +wrote: +> Hi all, +> +> I'm currently the maintainer of Jim Tcl trying as best as I can +> to fill Salvatore's shoes. +> +> Short story: +> +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. +> +> Once I have a record of all contributors agreeing to switch +> to a FreeBSD license, I'll update CVS. +> +> Long story: +> +> The current Jim Tcl license has a problem with GPL. If you +> link GPL code and Jim Tcl, the result is no license at all. +> +> This prevents Jim Tcl from being used in GPL projects. +> +> Lately Jim Tcl has been used with OpenOCD, a GPL project, +> and the license issue must be resolved one way or another. +> +> Upon conferring with Jonathan Larmour <jifl@ecoscentric.com>, who +> has kindly helped out with his knowledge on the topic, I have +> concluded that the best way to rectify this is to change the +> Jim Tcl license to a FreeBSD license. See OpenOCD mailing +> list for a discussion on this if you want details. +> +> http://www.fsf.org/licensing/licenses/index_html#FreeBSD +> +> As far as I can determine, below is the complete list of contributors. +> +> +> antirez - Salvatore Sanfilippo <antirez@gmail.com> +> patthoyts - ?? Pat Thoyts <patthoyts@users.sf.net> +> oharboe - =D8yvind Harboe - soyvind.harboe@zylin.com +> chi - ?? +> Andrew Lunn <andrew@lunn.ch> +> Duane Ellis <openocd@duaneellis.com> +> Uwe Klein <uklein@klein-messgeraete.de> +> Clemens Hintze ml-jim@qiao.in-berlin.de +> +> Please let me know if any of the emails below are wrong(chi is +> missing) or the list is not complete. +> +> +> -- +> =D8yvind Harboe +> http://www.zylin.com/zy1000.html +> ARM7 ARM9 XScale Cortex +> JTAG debugger and flash programmer +> + + + +--=20 +=D8yvind Harboe +http://www.zylin.com/zy1000.html +ARM7 ARM9 XScale Cortex +JTAG debugger and flash programmer diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt new file mode 100755 index 0000000..988a599 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/pat.txt @@ -0,0 +1,84 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs108097ang; + Wed, 16 Jul 2008 07:49:02 -0700 (PDT) +Received: by 10.142.232.20 with SMTP id e20mr80874wfh.138.1216219741865; + Wed, 16 Jul 2008 07:49:01 -0700 (PDT) +Return-Path: <patthoyts@users.sourceforge.net> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 30si10551683wff.18.2008.07.16.07.49.01; + Wed, 16 Jul 2008 07:49:01 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of patthoyts@users.sourceforge.net) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by best guess record for domain of patthoyts@users.sourceforge.net) smtp.mail=patthoyts@users.sourceforge.net +Received: from smtp-out4.blueyonder.co.uk ([195.188.213.7]:38596) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <patthoyts@users.sourceforge.net>) + id 1KJ8JH-0000Vd-OT + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 16:48:52 +0200 +Received: from [172.23.170.141] (helo=anti-virus02-08) + by smtp-out4.blueyonder.co.uk with smtp (Exim 4.52) + id 1KJ8JO-0007r0-Cy; Wed, 16 Jul 2008 15:48:58 +0100 +Received: from [77.102.249.21] (helo=badger.patthoyts.tk) + by asmtp-out4.blueyonder.co.uk with esmtp (Exim 4.52) + id 1KJ8J6-0000gY-VY; Wed, 16 Jul 2008 15:48:41 +0100 +Received: by badger.patthoyts.tk (Postfix, from userid 1000) + id 810535184F; Wed, 16 Jul 2008 15:48:40 +0100 (BST) +Sender: pat@badger.patthoyts.tk +To: =?iso-8859-1?q?=D8yvind_Harboe?= <oyvind.harboe@zylin.com> +Cc: jim-devel@lists.berlios.de +Subject: Re: Change Jim Tcl license +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Face: .`d#euqz@6H{";Ysmx2IVe_7M3vA+2w1X[QLk?ZO&QRauXQL{*L'$3getx}9+zK.-KWDx3. + qrlR)76MFb`6bgoGvLpLtcQKB=X~;*<JKLtwLBM(IA'?rVjs1*tq\VHn?WMNsB,3XXWF@5.)4SRFa+ + '?a?.s#@hl7CiTo'F"O!fvbL0 +X-Url: http://www.patthoyts.tk/ +From: Pat Thoyts <patthoyts@users.sourceforge.net> +Date: 16 Jul 2008 15:48:39 +0100 +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +Message-ID: <87fxq97um0.fsf@badger.patthoyts.tk> +Lines: 27 +User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - users.sourceforge.net +X-Source: +X-Source-Args: +X-Source-Dir: + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +"=D8yvind Harboe" <oyvind.harboe@zylin.com> writes: + +>If you have contributed to Jim Tcl, please reply to this email +>that you agree that we can switch Jim Tcl to a FreeBSD license. +> +>Once I have a record of all contributors agreeing to switch +>to a FreeBSD license, I'll update CVS. + +I hereby agree to permit my contributions to the Jim project to be +re-licensed under a BSD compatible license. + +- --=20 +Pat Thoyts http://www.patthoyts.tk/ +PGP fingerprint 2C 6E 98 07 2C 59 C8 97 10 CE 11 E6 04 E0 B9 DD +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.8 (SunOS) +Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/> + +iQCVAwUBSH4KO2B90JXwhOSJAQKtqQP9ERwSXpbP69l4JSrunG29Rhu2F3r83zu3 +GAKpFu4HwkVnIStLQ4o3tsqG9uKrVDbRMa187eSwHmlXXIMwDlkCKNsDFxvdLDZz +kbTYDibspYSw6CjwOUSTXifK9P7ho4Q7PtsRnJ8T1IMlGJlwg39Rxd+mpEO/if3q +ExIwM1aBbAs=3D +=3Du8si +-----END PGP SIGNATURE----- + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt new file mode 100755 index 0000000..5bbf973 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/salvatore.txt @@ -0,0 +1,88 @@ + +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs113143ang; + Wed, 16 Jul 2008 08:41:11 -0700 (PDT) +Received: by 10.142.140.15 with SMTP id n15mr127048wfd.84.1216222870242; + Wed, 16 Jul 2008 08:41:10 -0700 (PDT) +Return-Path: <antirez@gmail.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 29si7397124wfg.0.2008.07.16.08.41.08; + Wed, 16 Jul 2008 08:41:10 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of antirez@gmail.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of antirez@gmail.com) smtp.mail=antirez@gmail.com; dkim=pass (test mode) header.i=@gmail.com +Received: from fg-out-1718.google.com ([72.14.220.155]:16058) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <antirez@gmail.com>) + id 1KJ97g-0004yX-1W + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 17:40:59 +0200 +Received: by fg-out-1718.google.com with SMTP id l27so3985052fgb.19 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 08:40:59 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=gamma; + h=domainkey-signature:received:received:message-id:date:from:to + :subject:cc:in-reply-to:mime-version:content-type + :content-transfer-encoding:content-disposition:references; + bh=/aWDZQfgMBPqomYWZ2AUKOhhGMju+bwnSBbKL8MBonA=; + b=i0P3OKDopn/vHfa5ZrUvBjuPBnj43GMw8FOXKjxM/IfvywJParYqBS2Vmlw8RTndFg + J5wwxXf5056cZu/GbKbj8xLfylFfSInVaO7OnDutA3CeX1iU35my1DU6l9W6ILkLiT1P + Azi3L27rFQrzau/s53VU/UVELc3WckWdu1a1k= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=gmail.com; s=gamma; + h=message-id:date:from:to:subject:cc:in-reply-to:mime-version + :content-type:content-transfer-encoding:content-disposition + :references; + b=ww2MIz9svJttgS8mTRBhEX8Isveugn2hl3sMcgh0hZ1+ln8YbiysxYxZkdddewWm02 + WXsWgSgwy7MIPAUK1tNjzgkZ2l789SdrAtBCmqmRWJJI+ESTqbHMz8cqW+QRVP/A9Dfm + 8+AR85DHi7SOB0mdHtq9fsavZReUdaSIgy6F4= +Received: by 10.86.80.5 with SMTP id d5mr2284433fgb.19.1216222858224; + Wed, 16 Jul 2008 08:40:58 -0700 (PDT) +Received: by 10.86.50.18 with HTTP; Wed, 16 Jul 2008 08:40:58 -0700 (PDT) +Message-ID: <c6114db60807160840n62186f46w7cdc1bbec91186ca@mail.gmail.com> +Date: Wed, 16 Jul 2008 17:40:58 +0200 +From: "Salvatore Sanfilippo" <antirez@gmail.com> +To: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Subject: Re: Change Jim Tcl license +Cc: jim-devel@lists.berlios.de, patthoyts@users.sf.net, andrew@lunn.ch, + openocd@duaneellis.com, uklein@klein-messgeraete.de, + ml-jim@qiao.in-berlin.de +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - gmail.com +X-Source: +X-Source-Args: +X-Source-Dir: + +I agree to permit my contributions to the Jim project to be +re-licensed under a BSD compatible license. + +Since I'm currently the top contributor if it's safer from +the legal point of view I can also put a tar.gz of the current +Jim source code with a BSD "LICENSE" file on my website. + +Otherwise I can sign by hand a letter and send a digitalized +image here. + +Ciao, +Salvatore + +-- +Salvatore 'antirez' Sanfilippo +http://antirez.com + +Organizations which design systems are constrained to produce designs +which are copies of the communication structures of these +organizations. + +Conway's Law diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt new file mode 100755 index 0000000..035ca32 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/freebsd/uwe.txt @@ -0,0 +1,73 @@ +Delivered-To: oyvindharboe@gmail.com +Received: by 10.100.7.20 with SMTP id 20cs89014ang; + Wed, 16 Jul 2008 01:58:32 -0700 (PDT) +Received: by 10.142.125.9 with SMTP id x9mr5028534wfc.123.1216198711465; + Wed, 16 Jul 2008 01:58:31 -0700 (PDT) +Return-Path: <wiederling@googlemail.com> +Received: from cpanel5.proisp.no (cpanel5.proisp.no [209.85.100.29]) + by mx.google.com with ESMTP id 30si6756166wfa.10.2008.07.16.01.58.29; + Wed, 16 Jul 2008 01:58:31 -0700 (PDT) +Received-SPF: neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of wiederling@googlemail.com) client-ip=209.85.100.29; +Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.100.29 is neither permitted nor denied by domain of wiederling@googlemail.com) smtp.mail=wiederling@googlemail.com; dkim=pass (test mode) header.i=@googlemail.com +Received: from wr-out-0506.google.com ([64.233.184.233]:51225) + by cpanel5.proisp.no with esmtp (Exim 4.69) + (envelope-from <wiederling@googlemail.com>) + id 1KJ2q7-00057b-IR + for oyvind.harboe@zylin.com; Wed, 16 Jul 2008 10:58:24 +0200 +Received: by wr-out-0506.google.com with SMTP id c8so2209154wra.27 + for <oyvind.harboe@zylin.com>; Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=googlemail.com; s=gamma; + h=domainkey-signature:received:received:message-id:date:from:to + :subject:cc:in-reply-to:mime-version:content-type + :content-transfer-encoding:content-disposition:references; + bh=VxcH0g2H5iLUo27gqJiqrlY4uVbN1NFE4skyMKqysPM=; + b=JPK53r6LQ6GqBCG1kfVYyTPuPuVhlBrbzQ8oSBwpwuwwB7t3CSv+c75jRjb/n3y8mi + gN1r6noZucK9ZpRZiHxYZpHVhYFcWbZ+ZXM75H2qIFfl4YDzfgg/Ub7CzoR2LskuBsRk + DMH2LnyAYf+Om2YAKJdkoMnGbPMDMFSrNHeIc= +DomainKey-Signature: a=rsa-sha1; c=nofws; + d=googlemail.com; s=gamma; + h=message-id:date:from:to:subject:cc:in-reply-to:mime-version + :content-type:content-transfer-encoding:content-disposition + :references; + b=VAGlxpb1YGbex/eaS0tQgWvH/lWHzgD5R/rxjshVSwZJOStwqMA1F5jNQgybQFIn1F + zWoiAV81uWMzBEGYab7SGsStWLxovcBSgi9NL+XqwAkhBdrWjgFPvpBHn5PvgOOXEhGH + EGhjrY8qp2LSxhFcW3/DvgObhBBKtY1J+qzvA= +Received: by 10.90.115.17 with SMTP id n17mr1231758agc.90.1216198705850; + Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +Received: by 10.90.105.18 with HTTP; Wed, 16 Jul 2008 01:58:25 -0700 (PDT) +Message-ID: <1af31b6f0807160158o295303adh43abdd34fbe8ec99@mail.gmail.com> +Date: Wed, 16 Jul 2008 10:58:25 +0200 +From: "Uwe Klein" <wiederling@googlemail.com> +To: "=?ISO-8859-1?Q?=D8yvind_Harboe?=" <oyvind.harboe@zylin.com> +Subject: Re: [Jim-devel] Change Jim Tcl license +Cc: jim-devel@lists.berlios.de, patthoyts@users.sf.net, andrew@lunn.ch, + uklein@klein-messgeraete.de, antirez@gmail.com, + openocd@duaneellis.com, ml-jim@qiao.in-berlin.de +In-Reply-To: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +MIME-Version: 1.0 +Content-Type: text/plain; charset=ISO-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline +References: <c09652430807160034pd4a5b0q18f69a219827e111@mail.gmail.com> +X-Spam-Status: No, score=-2.6 +X-Spam-Score: -25 +X-Spam-Bar: -- +X-Spam-Flag: NO +X-AntiAbuse: This header was added to track abuse, please include it with any abuse report +X-AntiAbuse: Primary Hostname - cpanel5.proisp.no +X-AntiAbuse: Original Domain - zylin.com +X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] +X-AntiAbuse: Sender Address Domain - googlemail.com +X-Source: +X-Source-Args: +X-Source-Dir: + +> If you have contributed to Jim Tcl, please reply to this email +> that you agree that we can switch Jim Tcl to a FreeBSD license. + +For Uwe Klein <uklein@klein-messgeraete.de> + +This is OK with me. + +uwe diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/glob.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/glob.tcl new file mode 100755 index 0000000..cd94d8d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/glob.tcl @@ -0,0 +1,129 @@ +# Implements a Tcl-compatible glob command based on readdir +# +# (c) 2008 Steve Bennett <steveb@workware.net.au> +# +# See LICENCE in this directory for licensing. + +package require readdir + +# Implements the Tcl glob command +# +# Usage: glob ?-nocomplain? pattern ... +# +# Patterns use 'string match' (glob) pattern matching for each +# directory level, plus support for braced alternations. +# +# e.g. glob "te[a-e]*/*.{c,tcl}" +# +# Note: files starting with . will only be returned if matching component +# of the pattern starts with . +proc glob {args} { + + # If $dir is a directory, return a list of all entries + # it contains which match $pattern + # + local proc glob.readdir_pattern {dir pattern} { + set result {} + + # readdir doesn't return . or .., so simulate it here + if {$pattern in {. ..}} { + return $pattern + } + + # If the pattern isn't actually a pattern... + if {[string match {*[*?]*} $pattern]} { + # Use -nocomplain here to return nothing if $dir is not a directory + set files [readdir -nocomplain $dir] + } elseif {[file isdir $dir] && [file exists $dir/$pattern]} { + set files [list $pattern] + } else { + set files "" + } + + foreach name $files { + if {[string match $pattern $name]} { + # Only include entries starting with . if the pattern starts with . + if {[string index $name 0] eq "." && [string index $pattern 0] ne "."} { + continue + } + lappend result $name + } + } + + return $result + } + + # If the pattern contains a braced expression, return a list of + # patterns with the braces expanded. {c,b}* => c* b* + # Otherwise just return the pattern + # Note: Only supports one braced expression. i.e. not {a,b}*{c,d}* + proc glob.expandbraces {pattern} { + # Avoid regexp for dependency reasons. + # XXX: Doesn't handle backslashed braces + if {[set fb [string first "\{" $pattern]] < 0} { + return $pattern + } + if {[set nb [string first "\}" $pattern $fb]] < 0} { + return $pattern + } + set before [string range $pattern 0 $fb-1] + set braced [string range $pattern $fb+1 $nb-1] + set after [string range $pattern $nb+1 end] + + lmap part [split $braced ,] { + set pat $before$part$after + } + } + + # Core glob implementation. Returns a list of files/directories matching the pattern + proc glob.glob {pattern} { + set dir [file dirname $pattern] + if {$dir eq $pattern} { + # At the top level + return [list $dir] + } + + # Recursively expand the parent directory + set dirlist [glob.glob $dir] + set pattern [file tail $pattern] + + # Now collect the fiels/directories + set result {} + foreach dir $dirlist { + set globdir $dir + if {[string match "*/" $dir]} { + set sep "" + } elseif {$dir eq "."} { + set globdir "" + set sep "" + } else { + set sep / + } + foreach pat [glob.expandbraces $pattern] { + foreach name [glob.readdir_pattern $dir $pat] { + lappend result $globdir$sep$name + } + } + } + return $result + } + + # Start of main glob + set nocomplain 0 + + if {[lindex $args 0] eq "-nocomplain"} { + set nocomplain 1 + set args [lrange $args 1 end] + } + + set result {} + foreach pattern $args { + lappend result {*}[glob.glob $pattern] + } + + if {$nocomplain == 0 && [llength $result] == 0} { + return -code error "no files matched glob patterns" + } + + return $result +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl new file mode 100755 index 0000000..a764f3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/initjimsh.tcl @@ -0,0 +1,27 @@ +# This pseudo-package is loaded from jimsh to add additional +# paths to $auto_path and to source ~/.jimrc + +proc _jimsh_init {} { + rename _jimsh_init {} + + # Add to the standard auto_path + lappend p {*}[split [env JIMLIB {}] $::tcl_platform(pathSeparator)] + lappend p {*}$::auto_path + lappend p [file dirname [info nameofexecutable]] + set ::auto_path $p + + if {$::tcl_interactive && [env HOME {}] ne ""} { + foreach src {.jimrc jimrc.tcl} { + if {[file exists [env HOME]/$src]} { + uplevel #0 source [env HOME]/$src + break + } + } + } +} + +if {$tcl_platform(platform) eq "windows"} { + set jim_argv0 [string map {\\ /} $jim_argv0] +} + +_jimsh_init diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-aio.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-aio.c new file mode 100755 index 0000000..710a47d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-aio.c @@ -0,0 +1,1353 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#include "jim.h" +#include "jimautoconf.h" + +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#else +#define JIM_ANSIC +#endif + +#include "jim-eventloop.h" +#include "jim-subcmd.h" + +#define AIO_CMD_LEN 32 /* e.g. aio.handleXXXXXX */ +#define AIO_BUF_LEN 256 /* Can keep this small and rely on stdio buffering */ + +#define AIO_KEEPOPEN 1 + +#if defined(JIM_IPV6) +#define IPV6 1 +#else +#define IPV6 0 +#ifndef PF_INET6 +#define PF_INET6 0 +#endif +#endif + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +union sockaddr_any { + struct sockaddr sa; + struct sockaddr_in sin; +#if IPV6 + struct sockaddr_in6 sin6; +#endif +}; + +#ifndef HAVE_INET_NTOP +const char *inet_ntop(int af, const void *src, char *dst, int size) +{ + if (af != PF_INET) { + return NULL; + } + snprintf(dst, size, "%s", inet_ntoa(((struct sockaddr_in *)src)->sin_addr)); + return dst; +} +#endif +#endif /* JIM_BOOTSTRAP */ + +typedef struct AioFile +{ + FILE *fp; + Jim_Obj *filename; + int type; + int OpenFlags; /* AIO_KEEPOPEN? keep FILE* */ + int fd; +#ifdef O_NDELAY + int flags; +#endif + Jim_Obj *rEvent; + Jim_Obj *wEvent; + Jim_Obj *eEvent; + int addr_family; +} AioFile; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode); + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +static int JimParseIPv6Address(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen) +{ +#if IPV6 + /* + * An IPv6 addr/port looks like: + * [::1] + * [::1]:2000 + * [fe80::223:6cff:fe95:bdc0%en1]:2000 + * [::]:2000 + * 2000 + * + * Note that the "any" address is ::, which is the same as when no address is specified. + */ + char *sthost = NULL; + const char *stport; + int ret = JIM_OK; + struct addrinfo req; + struct addrinfo *ai; + + stport = strrchr(hostport, ':'); + if (!stport) { + /* No : so, the whole thing is the port */ + stport = hostport; + hostport = "::"; + sthost = Jim_StrDup(hostport); + } + else { + stport++; + } + + if (*hostport == '[') { + /* This is a numeric ipv6 address */ + char *pt = strchr(++hostport, ']'); + if (pt) { + sthost = Jim_StrDupLen(hostport, pt - hostport); + } + } + + if (!sthost) { + sthost = Jim_StrDupLen(hostport, stport - hostport - 1); + } + + memset(&req, '\0', sizeof(req)); + req.ai_family = PF_INET6; + + if (getaddrinfo(sthost, NULL, &req, &ai)) { + Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport); + ret = JIM_ERR; + } + else { + memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen); + *salen = ai->ai_addrlen; + + sa->sin.sin_port = htons(atoi(stport)); + + freeaddrinfo(ai); + } + Jim_Free(sthost); + + return ret; +#else + Jim_SetResultString(interp, "ipv6 not supported", -1); + return JIM_ERR; +#endif +} + +static int JimParseIpAddress(Jim_Interp *interp, const char *hostport, union sockaddr_any *sa, int *salen) +{ + /* An IPv4 addr/port looks like: + * 192.168.1.5 + * 192.168.1.5:2000 + * 2000 + * + * If the address is missing, INADDR_ANY is used. + * If the port is missing, 0 is used (only useful for server sockets). + */ + char *sthost = NULL; + const char *stport; + int ret = JIM_OK; + + stport = strrchr(hostport, ':'); + if (!stport) { + /* No : so, the whole thing is the port */ + stport = hostport; + sthost = Jim_StrDup("0.0.0.0"); + } + else { + sthost = Jim_StrDupLen(hostport, stport - hostport); + stport++; + } + + { +#ifdef HAVE_GETADDRINFO + struct addrinfo req; + struct addrinfo *ai; + memset(&req, '\0', sizeof(req)); + req.ai_family = PF_INET; + + if (getaddrinfo(sthost, NULL, &req, &ai)) { + ret = JIM_ERR; + } + else { + memcpy(&sa->sin, ai->ai_addr, ai->ai_addrlen); + *salen = ai->ai_addrlen; + freeaddrinfo(ai); + } +#else + struct hostent *he; + + ret = JIM_ERR; + + if ((he = gethostbyname(sthost)) != NULL) { + if (he->h_length == sizeof(sa->sin.sin_addr)) { + *salen = sizeof(sa->sin); + sa->sin.sin_family= he->h_addrtype; + memcpy(&sa->sin.sin_addr, he->h_addr, he->h_length); /* set address */ + ret = JIM_OK; + } + } +#endif + + sa->sin.sin_port = htons(atoi(stport)); + } + Jim_Free(sthost); + + if (ret != JIM_OK) { + Jim_SetResultFormatted(interp, "Not a valid address: %s", hostport); + } + + return ret; +} + +#ifdef HAVE_SYS_UN_H +static int JimParseDomainAddress(Jim_Interp *interp, const char *path, struct sockaddr_un *sa) +{ + sa->sun_family = PF_UNIX; + snprintf(sa->sun_path, sizeof(sa->sun_path), "%s", path); + + return JIM_OK; +} +#endif +#endif /* JIM_BOOTSTRAP */ + +static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name) +{ + if (name) { + Jim_SetResultFormatted(interp, "%#s: %s", name, strerror(errno)); + } + else { + Jim_SetResultString(interp, strerror(errno), -1); + } +} + +static void JimAioDelProc(Jim_Interp *interp, void *privData) +{ + AioFile *af = privData; + + JIM_NOTUSED(interp); + + Jim_DecrRefCount(interp, af->filename); + + if (!(af->OpenFlags & AIO_KEEPOPEN)) { + fclose(af->fp); + } +#ifdef jim_ext_eventloop + /* remove existing EventHandlers */ + if (af->rEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } + if (af->wEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } + if (af->eEvent) { + Jim_DeleteFileHandler(interp, af->fp); + } +#endif + Jim_Free(af); +} + +static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int nonewline = 0; + int neededLen = -1; /* -1 is "read as much as possible" */ + + if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + nonewline = 1; + argv++; + argc--; + } + if (argc == 1) { + jim_wide wideValue; + + if (Jim_GetWide(interp, argv[0], &wideValue) != JIM_OK) + return JIM_ERR; + if (wideValue < 0) { + Jim_SetResultString(interp, "invalid parameter: negative len", -1); + return JIM_ERR; + } + neededLen = (int)wideValue; + } + else if (argc) { + return -1; + } + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (neededLen != 0) { + int retval; + int readlen; + + if (neededLen == -1) { + readlen = AIO_BUF_LEN; + } + else { + readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); + } + retval = fread(buf, 1, readlen, af->fp); + if (retval > 0) { + Jim_AppendString(interp, objPtr, buf, retval); + if (neededLen != -1) { + neededLen -= retval; + } + } + if (retval != readlen) + break; + } + /* Check for error conditions */ + if (ferror(af->fp)) { + clearerr(af->fp); + /* eof and EAGAIN are not error conditions */ + if (!feof(af->fp) && errno != EAGAIN) { + /* I/O error */ + Jim_FreeNewObj(interp, objPtr); + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + } + if (nonewline) { + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + long count = 0; + long maxlen = LONG_MAX; + FILE *outfh = Jim_AioFilehandle(interp, argv[0]); + + if (outfh == NULL) { + return JIM_ERR; + } + + if (argc == 2) { + if (Jim_GetLong(interp, argv[1], &maxlen) != JIM_OK) { + return JIM_ERR; + } + } + + while (count < maxlen) { + int ch = fgetc(af->fp); + + if (ch == EOF || fputc(ch, outfh) == EOF) { + break; + } + count++; + } + + if (ferror(af->fp)) { + Jim_SetResultFormatted(interp, "error while reading: %s", strerror(errno)); + clearerr(af->fp); + return JIM_ERR; + } + + if (ferror(outfh)) { + Jim_SetResultFormatted(interp, "error while writing: %s", strerror(errno)); + clearerr(outfh); + return JIM_ERR; + } + + Jim_SetResultInt(interp, count); + + return JIM_OK; +} + +static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int len; + + errno = 0; + + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (1) { + buf[AIO_BUF_LEN - 1] = '_'; + if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL) + break; + + if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') { + Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1); + } + else { + len = strlen(buf); + + if (len && (buf[len - 1] == '\n')) { + /* strip "\n" */ + len--; + } + + Jim_AppendString(interp, objPtr, buf, len); + break; + } + } + if (ferror(af->fp) && errno != EAGAIN && errno != EINTR) { + /* I/O error */ + Jim_FreeNewObj(interp, objPtr); + JimAioSetError(interp, af->filename); + clearerr(af->fp); + return JIM_ERR; + } + + if (argc) { + if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + return JIM_ERR; + } + + len = Jim_Length(objPtr); + + if (len == 0 && feof(af->fp)) { + /* On EOF returns -1 if varName was specified */ + len = -1; + } + Jim_SetResultInt(interp, len); + } + else { + Jim_SetResult(interp, objPtr); + } + return JIM_OK; +} + +static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int wlen; + const char *wdata; + Jim_Obj *strObj; + + if (argc == 2) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + return -1; + } + strObj = argv[1]; + } + else { + strObj = argv[0]; + } + + wdata = Jim_GetString(strObj, &wlen); + if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) { + if (argc == 2 || putc('\n', af->fp) != EOF) { + return JIM_OK; + } + } + JimAioSetError(interp, af->filename); + return JIM_ERR; +} + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) +static int aio_cmd_recvfrom(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char *buf; + union sockaddr_any sa; + long len; + socklen_t salen = sizeof(sa); + int rlen; + + if (Jim_GetLong(interp, argv[0], &len) != JIM_OK) { + return JIM_ERR; + } + + buf = Jim_Alloc(len + 1); + + rlen = recvfrom(fileno(af->fp), buf, len, 0, &sa.sa, &salen); + if (rlen < 0) { + Jim_Free(buf); + JimAioSetError(interp, NULL); + return JIM_ERR; + } + buf[rlen] = 0; + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, rlen)); + + if (argc > 1) { + /* INET6_ADDRSTRLEN is 46. Add some for [] and port */ + char addrbuf[60]; + +#if IPV6 + if (sa.sa.sa_family == PF_INET6) { + addrbuf[0] = '['; + /* Allow 9 for []:65535\0 */ + inet_ntop(sa.sa.sa_family, &sa.sin6.sin6_addr, addrbuf + 1, sizeof(addrbuf) - 9); + snprintf(addrbuf + strlen(addrbuf), 8, "]:%d", ntohs(sa.sin.sin_port)); + } + else +#endif + { + /* Allow 7 for :65535\0 */ + inet_ntop(sa.sa.sa_family, &sa.sin.sin_addr, addrbuf, sizeof(addrbuf) - 7); + snprintf(addrbuf + strlen(addrbuf), 7, ":%d", ntohs(sa.sin.sin_port)); + } + + if (Jim_SetVariable(interp, argv[1], Jim_NewStringObj(interp, addrbuf, -1)) != JIM_OK) { + return JIM_ERR; + } + } + + return JIM_OK; +} + + +static int aio_cmd_sendto(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int wlen; + int len; + const char *wdata; + union sockaddr_any sa; + const char *addr = Jim_String(argv[1]); + int salen; + + if (IPV6 && af->addr_family == PF_INET6) { + if (JimParseIPv6Address(interp, addr, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, addr, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + wdata = Jim_GetString(argv[0], &wlen); + + /* Note that we don't validate the socket type. Rely on sendto() failing if appropriate */ + len = sendto(fileno(af->fp), wdata, wlen, 0, &sa.sa, salen); + if (len < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + Jim_SetResultInt(interp, len); + return JIM_OK; +} + +static int aio_cmd_accept(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int sock; + union sockaddr_any sa; + socklen_t addrlen = sizeof(sa); + + sock = accept(af->fd, &sa.sa, &addrlen); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + /* Create the file command */ + return JimMakeChannel(interp, NULL, sock, Jim_NewStringObj(interp, "accept", -1), + "aio.sockstream%ld", af->addr_family, "r+"); +} + +static int aio_cmd_listen(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + long backlog; + + if (Jim_GetLong(interp, argv[0], &backlog) != JIM_OK) { + return JIM_ERR; + } + + if (listen(af->fd, backlog)) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + return JIM_OK; +} +#endif /* JIM_BOOTSTRAP */ + +static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + if (fflush(af->fp) == EOF) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, feof(af->fp)); + return JIM_OK; +} + +static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_DeleteCommand(interp, Jim_String(argv[0])); + return JIM_OK; +} + +static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int orig = SEEK_SET; + long offset; + + if (argc == 2) { + if (Jim_CompareStringImmediate(interp, argv[1], "start")) + orig = SEEK_SET; + else if (Jim_CompareStringImmediate(interp, argv[1], "current")) + orig = SEEK_CUR; + else if (Jim_CompareStringImmediate(interp, argv[1], "end")) + orig = SEEK_END; + else { + return -1; + } + } + if (Jim_GetLong(interp, argv[0], &offset) != JIM_OK) { + return JIM_ERR; + } + if (fseek(af->fp, offset, orig) == -1) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, ftell(af->fp)); + return JIM_OK; +} + +static int aio_cmd_filename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResult(interp, af->filename); + return JIM_OK; +} + +#ifdef O_NDELAY +static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + int fmode = af->flags; + + if (argc) { + long nb; + + if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { + return JIM_ERR; + } + if (nb) { + fmode |= O_NDELAY; + } + else { + fmode &= ~O_NDELAY; + } + fcntl(af->fd, F_SETFL, fmode); + af->flags = fmode; + } + Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); + return JIM_OK; +} +#endif + +static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + static const char * const options[] = { + "none", + "line", + "full", + NULL + }; + enum + { + OPT_NONE, + OPT_LINE, + OPT_FULL, + }; + int option; + + if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NONE: + setvbuf(af->fp, NULL, _IONBF, 0); + break; + case OPT_LINE: + setvbuf(af->fp, NULL, _IOLBF, BUFSIZ); + break; + case OPT_FULL: + setvbuf(af->fp, NULL, _IOFBF, BUFSIZ); + break; + } + return JIM_OK; +} + +#ifdef jim_ext_eventloop +static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_DecrRefCount(interp, objPtr); +} + +static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask) +{ + Jim_Obj *objPtr = clientData; + + return Jim_EvalObjBackground(interp, objPtr); +} + +static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, + int argc, Jim_Obj * const *argv) +{ + int scriptlen = 0; + + if (argc == 0) { + /* Return current script */ + if (*scriptHandlerObj) { + Jim_SetResult(interp, *scriptHandlerObj); + } + return JIM_OK; + } + + if (*scriptHandlerObj) { + /* Delete old handler */ + Jim_DeleteFileHandler(interp, af->fp); + *scriptHandlerObj = NULL; + } + + /* Now possibly add the new script(s) */ + Jim_GetString(argv[0], &scriptlen); + if (scriptlen == 0) { + /* Empty script, so done */ + return JIM_OK; + } + + /* A new script to add */ + Jim_IncrRefCount(argv[0]); + *scriptHandlerObj = argv[0]; + + Jim_CreateFileHandler(interp, af->fp, mask, + JimAioFileEventHandler, *scriptHandlerObj, JimAioFileEventFinalizer); + + return JIM_OK; +} + +static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv); +} + +static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv); +} + +static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->wEvent, argc, argv); +} +#endif + +static const jim_subcmd_type aio_command_table[] = { + { .cmd = "read", + .args = "?-nonewline? ?len?", + .function = aio_cmd_read, + .minargs = 0, + .maxargs = 2, + .description = "Read and return bytes from the stream. To eof if no len." + }, + { .cmd = "copyto", + .args = "handle ?size?", + .function = aio_cmd_copy, + .minargs = 1, + .maxargs = 2, + .description = "Copy up to 'size' bytes to the given filehandle, or to eof if no size." + }, + { .cmd = "gets", + .args = "?var?", + .function = aio_cmd_gets, + .minargs = 0, + .maxargs = 1, + .description = "Read one line and return it or store it in the var" + }, + { .cmd = "puts", + .args = "?-nonewline? str", + .function = aio_cmd_puts, + .minargs = 1, + .maxargs = 2, + .description = "Write the string, with newline unless -nonewline" + }, +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) + { .cmd = "recvfrom", + .args = "len ?addrvar?", + .function = aio_cmd_recvfrom, + .minargs = 1, + .maxargs = 2, + .description = "Receive up to 'len' bytes on the socket. Sets 'addrvar' with receive address, if set" + }, + { .cmd = "sendto", + .args = "str address", + .function = aio_cmd_sendto, + .minargs = 2, + .maxargs = 2, + .description = "Send 'str' to the given address (dgram only)" + }, + { .cmd = "accept", + .function = aio_cmd_accept, + .description = "Server socket only: Accept a connection and return stream" + }, + { .cmd = "listen", + .args = "backlog", + .function = aio_cmd_listen, + .minargs = 1, + .maxargs = 1, + .description = "Set the listen backlog for server socket" + }, +#endif /* JIM_BOOTSTRAP */ + { .cmd = "flush", + .function = aio_cmd_flush, + .description = "Flush the stream" + }, + { .cmd = "eof", + .function = aio_cmd_eof, + .description = "Returns 1 if stream is at eof" + }, + { .cmd = "close", + .flags = JIM_MODFLAG_FULLARGV, + .function = aio_cmd_close, + .description = "Closes the stream" + }, + { .cmd = "seek", + .args = "offset ?start|current|end", + .function = aio_cmd_seek, + .minargs = 1, + .maxargs = 2, + .description = "Seeks in the stream (default 'current')" + }, + { .cmd = "tell", + .function = aio_cmd_tell, + .description = "Returns the current seek position" + }, + { .cmd = "filename", + .function = aio_cmd_filename, + .description = "Returns the original filename" + }, +#ifdef O_NDELAY + { .cmd = "ndelay", + .args = "?0|1?", + .function = aio_cmd_ndelay, + .minargs = 0, + .maxargs = 1, + .description = "Set O_NDELAY (if arg). Returns current/new setting." + }, +#endif + { .cmd = "buffering", + .args = "none|line|full", + .function = aio_cmd_buffering, + .minargs = 1, + .maxargs = 1, + .description = "Sets buffering" + }, +#ifdef jim_ext_eventloop + { .cmd = "readable", + .args = "?readable-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_readable, + .description = "Returns script, or invoke readable-script when readable, {} to remove", + }, + { .cmd = "writable", + .args = "?writable-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_writable, + .description = "Returns script, or invoke writable-script when writable, {} to remove", + }, + { .cmd = "onexception", + .args = "?exception-script?", + .minargs = 0, + .maxargs = 1, + .function = aio_cmd_onexception, + .description = "Returns script, or invoke exception-script when oob data, {} to remove", + }, +#endif + { 0 } +}; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv); +} + +static int JimAioOpenCommand(Jim_Interp *interp, int argc, + Jim_Obj *const *argv) +{ + FILE *fp; + const char *hdlfmt; + const char *mode; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); + return JIM_ERR; + } + + mode = (argc == 3) ? Jim_String(argv[2]) : "r"; + hdlfmt = Jim_String(argv[1]); + if (Jim_CompareStringImmediate(interp, argv[1], "stdin")) { + fp = stdin; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "stdout")) { + fp = stdout; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "stderr")) { + fp = stderr; + } + else { + const char *filename = Jim_String(argv[1]); + + +#ifdef jim_ext_tclcompat + /* If the filename starts with '|', use popen instead */ + if (*filename == '|') { + Jim_Obj *evalObj[3]; + + evalObj[0] = Jim_NewStringObj(interp, "popen", -1); + evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); + evalObj[2] = Jim_NewStringObj(interp, mode, -1); + + return Jim_EvalObjVector(interp, 3, evalObj); + } +#endif + hdlfmt = "aio.handle%ld"; + fp = NULL; + } + + /* Create the file command */ + return JimMakeChannel(interp, fp, -1, argv[1], hdlfmt, 0, mode); +} + +/** + * Creates a channel for fh/fd/filename. + * + * If fh is not NULL, uses that as the channel (and set AIO_KEEPOPEN). + * Otherwise, if fd is >= 0, uses that as the chanel. + * Otherwise opens 'filename' with mode 'mode'. + * + * hdlfmt is a sprintf format for the filehandle. Anything with %ld at the end will do. + * mode is used for open or fdopen. + * + * Creates the command and sets the name as the current result. + */ +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode) +{ + AioFile *af; + char buf[AIO_CMD_LEN]; + int OpenFlags = 0; + + Jim_IncrRefCount(filename); + + if (fh == NULL) { + if (fd < 0) { + fh = fopen(Jim_String(filename), mode); + } + else { + fh = fdopen(fd, mode); + } + } + else { + OpenFlags = AIO_KEEPOPEN; + } + + if (fh == NULL) { + JimAioSetError(interp, filename); + close(fd); + Jim_DecrRefCount(interp, filename); + return JIM_ERR; + } + + /* Create the file command */ + af = Jim_Alloc(sizeof(*af)); + memset(af, 0, sizeof(*af)); + af->fp = fh; + af->fd = fileno(fh); + af->filename = filename; +#ifdef FD_CLOEXEC + if ((OpenFlags & AIO_KEEPOPEN) == 0) { + fcntl(af->fd, F_SETFD, FD_CLOEXEC); + af->OpenFlags = OpenFlags; + } +#endif +#ifdef O_NDELAY + af->flags = fcntl(af->fd, F_GETFL); +#endif + af->addr_family = family; + snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); + Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); + + Jim_SetResultString(interp, buf, -1); + + return JIM_OK; +} + +#if !defined(JIM_ANSIC) && !defined(JIM_BOOTSTRAP) + +static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *hdlfmt = "aio.unknown%ld"; + const char *socktypes[] = { + "unix", + "unix.server", + "dgram", + "dgram.server", + "stream", + "stream.server", + "pipe", + NULL + }; + enum + { + SOCK_UNIX, + SOCK_UNIX_SERVER, + SOCK_DGRAM_CLIENT, + SOCK_DGRAM_SERVER, + SOCK_STREAM_CLIENT, + SOCK_STREAM_SERVER, + SOCK_STREAM_PIPE, + SOCK_DGRAM6_CLIENT, + SOCK_DGRAM6_SERVER, + SOCK_STREAM6_CLIENT, + SOCK_STREAM6_SERVER, + }; + int socktype; + int sock; + const char *hostportarg = NULL; + int res; + int on = 1; + const char *mode = "r+"; + int family = PF_INET; + Jim_Obj *argv0 = argv[0]; + int ipv6 = 0; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-ipv6")) { + if (!IPV6) { + Jim_SetResultString(interp, "ipv6 not supported", -1); + return JIM_ERR; + } + ipv6 = 1; + family = PF_INET6; + } + argc -= ipv6; + argv += ipv6; + + if (argc < 2) { + wrongargs: + Jim_WrongNumArgs(interp, 1, &argv0, "?-ipv6? type ?address?"); + return JIM_ERR; + } + + if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + + Jim_SetEmptyResult(interp); + + hdlfmt = "aio.sock%ld"; + + if (argc > 2) { + hostportarg = Jim_String(argv[2]); + } + + switch (socktype) { + case SOCK_DGRAM_CLIENT: + if (argc == 2) { + /* No address, so an unconnected dgram socket */ + sock = socket(family, SOCK_DGRAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + break; + } + /* fall through */ + case SOCK_STREAM_CLIENT: + { + union sockaddr_any sa; + int salen; + + if (argc != 3) { + goto wrongargs; + } + + if (ipv6) { + if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + sock = socket(family, (socktype == SOCK_DGRAM_CLIENT) ? SOCK_DGRAM : SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + res = connect(sock, &sa.sa, salen); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + } + break; + + case SOCK_STREAM_SERVER: + case SOCK_DGRAM_SERVER: + { + union sockaddr_any sa; + int salen; + + if (argc != 3) { + goto wrongargs; + } + + if (ipv6) { + if (JimParseIPv6Address(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + } + else if (JimParseIpAddress(interp, hostportarg, &sa, &salen) != JIM_OK) { + return JIM_ERR; + } + sock = socket(family, (socktype == SOCK_DGRAM_SERVER) ? SOCK_DGRAM : SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + /* Enable address reuse */ + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); + + res = bind(sock, &sa.sa, salen); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + if (socktype == SOCK_STREAM_SERVER) { + res = listen(sock, 5); + if (res) { + JimAioSetError(interp, NULL); + close(sock); + return JIM_ERR; + } + } + hdlfmt = "aio.socksrv%ld"; + } + break; + +#ifdef HAVE_SYS_UN_H + case SOCK_UNIX: + { + struct sockaddr_un sa; + socklen_t len; + + if (argc != 3 || ipv6) { + goto wrongargs; + } + + if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { + JimAioSetError(interp, argv[2]); + return JIM_ERR; + } + family = PF_UNIX; + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); + res = connect(sock, (struct sockaddr *)&sa, len); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + hdlfmt = "aio.sockunix%ld"; + break; + } + + case SOCK_UNIX_SERVER: + { + struct sockaddr_un sa; + socklen_t len; + + if (argc != 3 || ipv6) { + goto wrongargs; + } + + if (JimParseDomainAddress(interp, hostportarg, &sa) != JIM_OK) { + JimAioSetError(interp, argv[2]); + return JIM_ERR; + } + family = PF_UNIX; + sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + len = strlen(sa.sun_path) + 1 + sizeof(sa.sun_family); + res = bind(sock, (struct sockaddr *)&sa, len); + if (res) { + JimAioSetError(interp, argv[2]); + close(sock); + return JIM_ERR; + } + res = listen(sock, 5); + if (res) { + JimAioSetError(interp, NULL); + close(sock); + return JIM_ERR; + } + hdlfmt = "aio.sockunixsrv%ld"; + break; + } +#endif + +#ifdef HAVE_PIPE + case SOCK_STREAM_PIPE: + { + int p[2]; + + if (argc != 2 || ipv6) { + goto wrongargs; + } + + if (pipe(p) < 0) { + JimAioSetError(interp, NULL); + return JIM_ERR; + } + + if (JimMakeChannel(interp, NULL, p[0], argv[1], "aio.pipe%ld", 0, "r") == JIM_OK) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + + if (JimMakeChannel(interp, NULL, p[1], argv[1], "aio.pipe%ld", 0, "w") == JIM_OK) { + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + /* Can only be here if fdopen() failed */ + close(p[0]); + close(p[1]); + JimAioSetError(interp, NULL); + return JIM_ERR; + } + break; +#endif + default: + Jim_SetResultString(interp, "Unsupported socket type", -1); + return JIM_ERR; + } + + return JimMakeChannel(interp, NULL, sock, argv[1], hdlfmt, family, mode); +} +#endif /* JIM_BOOTSTRAP */ + +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) +{ + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); + + if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { + return ((AioFile *) cmdPtr->u.native.privData)->fp; + } + Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); + return NULL; +} + +int Jim_aioInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); +#ifndef JIM_ANSIC + Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); +#endif + + /* Takeover stdin, stdout and stderr */ + Jim_EvalGlobal(interp, "open stdin; open stdout; open stderr"); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-array.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-array.c new file mode 100755 index 0000000..89a86f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-array.c @@ -0,0 +1,274 @@ + +/* + * Implements the array command for jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* Just a regular [info exists] */ + Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); + return JIM_OK; +} + +static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + int all = 0; + Jim_Obj *resultObj; + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (!objPtr) { + return JIM_OK; + } + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + all = 1; + } + + /* If it is a dictionary or list with an even number of elements, nothing else to do */ + if (all) { + if (Jim_IsDict(objPtr) || (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0)) { + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + if (all) { + /* Return the whole array */ + Jim_SetResult(interp, dictObj); + } + else { + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i + 1]); + } + } + + Jim_SetResult(interp, resultObj); + } + Jim_Free(dictValuesObj); + return JIM_OK; + +} + +static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (!objPtr) { + return JIM_OK; + } + + return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); +} + +static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr; + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + /* Unset the whole array */ + Jim_UnsetVariable(interp, argv[0], JIM_NONE); + return JIM_OK; + } + + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Create a new object with the values which don't match */ + resultObj = Jim_NewDictObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { + Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetVariable(interp, argv[0], resultObj); + return JIM_OK; +} + +static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int len = 0; + + /* Not found means zero length */ + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + if (objPtr) { + len = Jim_DictSize(interp, objPtr); + if (len < 0) { + return JIM_ERR; + } + } + + Jim_SetResultInt(interp, len); + + return JIM_OK; +} + +static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + int rc = JIM_OK; + Jim_Obj *listObj = argv[1]; + + if (Jim_GetVariable(interp, argv[0], JIM_NONE) == NULL) { + /* Doesn't exist, so just set the list directly */ + return Jim_SetVariable(interp, argv[0], listObj); + } + + len = Jim_ListLength(interp, listObj); + if (len % 2) { + Jim_SetResultString(interp, "list must have an even number of elements", -1); + return JIM_ERR; + } + for (i = 0; i < len && rc == JIM_OK; i += 2) { + Jim_Obj *nameObj; + Jim_Obj *valueObj; + + Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE); + Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE); + + rc = Jim_SetDictKeysVector(interp, argv[0], &nameObj, 1, valueObj, JIM_ERRMSG); + } + + return rc; +} + +static const jim_subcmd_type array_command_table[] = { + { .cmd = "exists", + .args = "arrayName", + .function = array_cmd_exists, + .minargs = 1, + .maxargs = 1, + .description = "Does array exist?" + }, + { .cmd = "get", + .args = "arrayName ?pattern?", + .function = array_cmd_get, + .minargs = 1, + .maxargs = 2, + .description = "Array contents as name value list" + }, + { .cmd = "names", + .args = "arrayName ?pattern?", + .function = array_cmd_names, + .minargs = 1, + .maxargs = 2, + .description = "Array keys as a list" + }, + { .cmd = "set", + .args = "arrayName list", + .function = array_cmd_set, + .minargs = 2, + .maxargs = 2, + .description = "Set array from list" + }, + { .cmd = "size", + .args = "arrayName", + .function = array_cmd_size, + .minargs = 1, + .maxargs = 1, + .description = "Number of elements in array" + }, + { .cmd = "unset", + .args = "arrayName ?pattern?", + .function = array_cmd_unset, + .minargs = 1, + .maxargs = 2, + .description = "Unset elements of an array" + }, + { .cmd = 0, + } +}; + +int Jim_arrayInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-clock.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-clock.c new file mode 100755 index 0000000..51ffb51 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-clock.c @@ -0,0 +1,159 @@ + +/* + * tcl_clock.c + * + * Implements the clock command + */ + +/* For strptime() */ +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <time.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* How big is big enough? */ + char buf[100]; + time_t t; + long seconds; + + const char *format = "%a %b %d %H:%M:%S %Z %Y"; + + if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { + return -1; + } + + if (argc == 3) { + format = Jim_String(argv[2]); + } + + if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { + return JIM_ERR; + } + t = seconds; + + strftime(buf, sizeof(buf), format, localtime(&t)); + + Jim_SetResultString(interp, buf, -1); + + return JIM_OK; +} + +#ifdef HAVE_STRPTIME +static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *pt; + struct tm tm; + time_t now = time(0); + + if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { + return -1; + } + + /* Initialise with the current date/time */ + localtime_r(&now, &tm); + + pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); + if (pt == 0 || *pt != 0) { + Jim_SetResultString(interp, "Failed to parse time according to format", -1); + return JIM_ERR; + } + + /* Now convert into a time_t */ + Jim_SetResultInt(interp, mktime(&tm)); + + return JIM_OK; +} +#endif + +static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResultInt(interp, time(NULL)); + + return JIM_OK; +} + +static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec); + + return JIM_OK; +} + +static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); + + return JIM_OK; +} + +static const jim_subcmd_type clock_command_table[] = { + { .cmd = "seconds", + .function = clock_cmd_seconds, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time as seconds since the epoch" + }, + { .cmd = "clicks", + .function = clock_cmd_micros, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in 'clicks'" + }, + { .cmd = "microseconds", + .function = clock_cmd_micros, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in microseconds" + }, + { .cmd = "milliseconds", + .function = clock_cmd_millis, + .minargs = 0, + .maxargs = 0, + .description = "Returns the current time in milliseconds" + }, + { .cmd = "format", + .args = "seconds ?-format format?", + .function = clock_cmd_format, + .minargs = 1, + .maxargs = 3, + .description = "Format the given time" + }, +#ifdef HAVE_STRPTIME + { .cmd = "scan", + .args = "str -format format", + .function = clock_cmd_scan, + .minargs = 3, + .maxargs = 3, + .description = "Determine the time according to the given format" + }, +#endif + { 0 } +}; + +int Jim_clockInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in new file mode 100755 index 0000000..2394bc5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-config.h.in @@ -0,0 +1,2 @@ +/* Public autoconf settings */ +@DEFINE_HAVE_LONG_LONG@ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c new file mode 100755 index 0000000..a7efdc2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.c @@ -0,0 +1,760 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-eventloop.h" + +/* POSIX includes */ +#include <sys/time.h> +#include <sys/types.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + +#if defined(__MINGW32__) +#include <windows.h> +#include <winsock.h> +#define msleep Sleep +#ifndef HAVE_USLEEP +#define usleep(US) msleep((US) / 1000) +#endif +#else +#include <sys/select.h> + +#ifndef HAVE_USLEEP +/* XXX: Implement this in terms of select() or nanosleep() */ +#define usleep(US) +#endif +#define msleep(MS) sleep((MS) / 1000); usleep(((MS) % 1000) * 1000); +#endif + +/* --- */ + +/* File event structure */ +typedef struct Jim_FileEvent +{ + FILE *handle; + int mask; /* one of JIM_EVENT_(READABLE|WRITABLE|EXCEPTION) */ + Jim_FileProc *fileProc; + Jim_EventFinalizerProc *finalizerProc; + void *clientData; + struct Jim_FileEvent *next; +} Jim_FileEvent; + +/* Time event structure */ +typedef struct Jim_TimeEvent +{ + jim_wide id; /* time event identifier. */ + int mode; /* restart, repetitive .. UK */ + long initialms; /* initial relativ timer value UK */ + long when_sec; /* seconds */ + long when_ms; /* milliseconds */ + Jim_TimeProc *timeProc; + Jim_EventFinalizerProc *finalizerProc; + void *clientData; + struct Jim_TimeEvent *next; +} Jim_TimeEvent; + +/* Per-interp stucture containing the state of the event loop */ +typedef struct Jim_EventLoop +{ + jim_wide timeEventNextId; + Jim_FileEvent *fileEventHead; + Jim_TimeEvent *timeEventHead; + int suppress_bgerror; /* bgerror returned break, so don't call it again */ +} Jim_EventLoop; + +static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData); +static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData); + +int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr) +{ + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + Jim_CallFrame *savedFramePtr; + int retval; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + retval = Jim_EvalObj(interp, scriptObjPtr); + interp->framePtr = savedFramePtr; + /* Try to report the error (if any) via the bgerror proc */ + if (retval != JIM_OK && !eventLoop->suppress_bgerror) { + Jim_Obj *objv[2]; + int rc = JIM_ERR; + + objv[0] = Jim_NewStringObj(interp, "bgerror", -1); + objv[1] = Jim_GetResult(interp); + Jim_IncrRefCount(objv[0]); + Jim_IncrRefCount(objv[1]); + if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || (rc = Jim_EvalObjVector(interp, 2, objv)) != JIM_OK) { + if (rc == JIM_BREAK) { + /* No more bgerror calls */ + eventLoop->suppress_bgerror++; + } + else { + /* Report the error to stderr. */ + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + /* And reset the result */ + Jim_SetResultString(interp, "", -1); + } + } + Jim_DecrRefCount(interp, objv[0]); + Jim_DecrRefCount(interp, objv[1]); + } + return retval; +} + + +void Jim_CreateFileHandler(Jim_Interp *interp, FILE * handle, int mask, + Jim_FileProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc) +{ + Jim_FileEvent *fe; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + fe = Jim_Alloc(sizeof(*fe)); + fe->handle = handle; + fe->mask = mask; + fe->fileProc = proc; + fe->finalizerProc = finalizerProc; + fe->clientData = clientData; + fe->next = eventLoop->fileEventHead; + eventLoop->fileEventHead = fe; +} + +void Jim_DeleteFileHandler(Jim_Interp *interp, FILE * handle) +{ + Jim_FileEvent *fe, *prev = NULL; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + fe = eventLoop->fileEventHead; + while (fe) { + if (fe->handle == handle) { + if (prev == NULL) + eventLoop->fileEventHead = fe->next; + else + prev->next = fe->next; + if (fe->finalizerProc) + fe->finalizerProc(interp, fe->clientData); + Jim_Free(fe); + return; + } + prev = fe; + fe = fe->next; + } +} + +static void JimGetTime(long *seconds, long *milliseconds) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + *seconds = tv.tv_sec; + *milliseconds = tv.tv_usec / 1000; +} + +jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide milliseconds, + Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc) +{ + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + jim_wide id = eventLoop->timeEventNextId++; + Jim_TimeEvent *te, *e, *prev; + long cur_sec, cur_ms; + + JimGetTime(&cur_sec, &cur_ms); + + te = Jim_Alloc(sizeof(*te)); + te->id = id; + te->mode = 0; + te->initialms = milliseconds; + te->when_sec = cur_sec + milliseconds / 1000; + te->when_ms = cur_ms + milliseconds % 1000; + if (te->when_ms >= 1000) { + te->when_sec++; + te->when_ms -= 1000; + } + te->timeProc = proc; + te->finalizerProc = finalizerProc; + te->clientData = clientData; + + /* Add to the appropriate place in the list */ + if (eventLoop->timeEventHead) { + prev = NULL; + for (e = eventLoop->timeEventHead; e; e = e->next) { + if (te->when_sec < e->when_sec || (te->when_sec == e->when_sec && te->when_ms < e->when_ms)) { + break; + } + prev = e; + } + if (prev) { + te->next = prev->next; + prev->next = te; + return id; + } + } + + te->next = eventLoop->timeEventHead; + eventLoop->timeEventHead = te; + + return id; +} + +static jim_wide JimParseAfterId(Jim_Obj *idObj) +{ + int len; + const char *tok = Jim_GetString(idObj, &len); + jim_wide id; + + if (strncmp(tok, "after#", 6) == 0 && Jim_StringToWide(tok + 6, &id, 10) == JIM_OK) { + /* Got an event by id */ + return id; + } + return -1; +} + +static jim_wide JimFindAfterByScript(Jim_EventLoop *eventLoop, Jim_Obj *scriptObj) +{ + Jim_TimeEvent *te; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + /* Is this an 'after' event? */ + if (te->timeProc == JimAfterTimeHandler) { + if (Jim_StringEqObj(scriptObj, te->clientData)) { + return te->id; + } + } + } + return -1; /* NO event with the specified ID found */ +} + +static Jim_TimeEvent *JimFindTimeHandlerById(Jim_EventLoop *eventLoop, jim_wide id) +{ + Jim_TimeEvent *te; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + if (te->id == id) { + return te; + } + } + return NULL; +} + +static Jim_TimeEvent *Jim_RemoveTimeHandler(Jim_EventLoop *eventLoop, jim_wide id) +{ + Jim_TimeEvent *te, *prev = NULL; + + for (te = eventLoop->timeEventHead; te; te = te->next) { + if (te->id == id) { + if (prev == NULL) + eventLoop->timeEventHead = te->next; + else + prev->next = te->next; + return te; + } + prev = te; + } + return NULL; +} + +static void Jim_FreeTimeHandler(Jim_Interp *interp, Jim_TimeEvent *te) +{ + if (te->finalizerProc) + te->finalizerProc(interp, te->clientData); + Jim_Free(te); +} + +jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id) +{ + Jim_TimeEvent *te; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + + if (id >= eventLoop->timeEventNextId) { + return -2; /* wrong event ID */ + } + + te = Jim_RemoveTimeHandler(eventLoop, id); + if (te) { + jim_wide remain; + long cur_sec, cur_ms; + + JimGetTime(&cur_sec, &cur_ms); + + remain = (te->when_sec - cur_sec) * 1000; + remain += (te->when_ms - cur_ms); + remain = (remain < 0) ? 0 : remain; + + Jim_FreeTimeHandler(interp, te); + return remain; + } + return -1; /* NO event with the specified ID found */ +} + +/* --- POSIX version of Jim_ProcessEvents, for now the only available --- */ + +/* Process every pending time event, then every pending file event + * (that may be registered by time event callbacks just processed). + * Without special flags the function sleeps until some file event + * fires, or when the next time event occurrs (if any). + * + * If flags is 0, the function does nothing and returns. + * if flags has JIM_ALL_EVENTS set, all the kind of events are processed. + * if flags has JIM_FILE_EVENTS set, file events are processed. + * if flags has JIM_TIME_EVENTS set, time events are processed. + * if flags has JIM_DONT_WAIT set the function returns ASAP until all + * the events that's possible to process without to wait are processed. + * + * The function returns the number of events processed or -1 if + * there are no matching handlers, or -2 on error. + */ +int Jim_ProcessEvents(Jim_Interp *interp, int flags) +{ + jim_wide sleep_ms = -1; + int processed = 0; + Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop"); + Jim_FileEvent *fe = eventLoop->fileEventHead; + Jim_TimeEvent *te; + jim_wide maxId; + + if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) { + /* No file events */ + if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) { + /* No time events */ + return -1; + } + } + + /* Note that we want call select() even if there are no + * file events to process as long as we want to process time + * events, in order to sleep until the next time event is ready + * to fire. */ + + if (flags & JIM_DONT_WAIT) { + /* Wait no time */ + sleep_ms = 0; + } + else if (flags & JIM_TIME_EVENTS) { + /* The nearest timer is always at the head of the list */ + if (eventLoop->timeEventHead) { + Jim_TimeEvent *shortest = eventLoop->timeEventHead; + long now_sec, now_ms; + + /* Calculate the time missing for the nearest + * timer to fire. */ + JimGetTime(&now_sec, &now_ms); + sleep_ms = 1000 * (shortest->when_sec - now_sec) + (shortest->when_ms - now_ms); + if (sleep_ms < 0) { + sleep_ms = 1; + } + } + else { + /* Wait forever */ + sleep_ms = -1; + } + } + +#ifdef HAVE_SELECT + if (flags & JIM_FILE_EVENTS) { + int retval; + struct timeval tv, *tvp = NULL; + fd_set rfds, wfds, efds; + int maxfd = -1; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + /* Check file events */ + while (fe != NULL) { + int fd = fileno(fe->handle); + + if (fe->mask & JIM_EVENT_READABLE) + FD_SET(fd, &rfds); + if (fe->mask & JIM_EVENT_WRITABLE) + FD_SET(fd, &wfds); + if (fe->mask & JIM_EVENT_EXCEPTION) + FD_SET(fd, &efds); + if (maxfd < fd) + maxfd = fd; + fe = fe->next; + } + + if (sleep_ms >= 0) { + tvp = &tv; + tvp->tv_sec = sleep_ms / 1000; + tvp->tv_usec = 1000 * (sleep_ms % 1000); + } + + retval = select(maxfd + 1, &rfds, &wfds, &efds, tvp); + + if (retval < 0) { + if (errno == EINVAL) { + /* This can happen on mingw32 if a non-socket filehandle is passed */ + Jim_SetResultString(interp, "non-waitable filehandle", -1); + return -2; + } + /* XXX: What about EINTR? */ + } + else if (retval > 0) { + fe = eventLoop->fileEventHead; + while (fe != NULL) { + int fd = fileno(fe->handle); + int mask = 0; + + if ((fe->mask & JIM_EVENT_READABLE) && FD_ISSET(fd, &rfds)) + mask |= JIM_EVENT_READABLE; + if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds)) + mask |= JIM_EVENT_WRITABLE; + if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds)) + mask |= JIM_EVENT_EXCEPTION; + + if (mask) { + if (fe->fileProc(interp, fe->clientData, mask) != JIM_OK) { + /* Remove the element on handler error */ + Jim_DeleteFileHandler(interp, fe->handle); + } + processed++; + /* After an event is processed our file event list + * may no longer be the same, so what we do + * is to clear the bit for this file descriptor and + * restart again from the head. */ + fe = eventLoop->fileEventHead; + FD_CLR(fd, &rfds); + FD_CLR(fd, &wfds); + FD_CLR(fd, &efds); + } + else { + fe = fe->next; + } + } + } + } +#else + if (sleep_ms > 0) { + msleep(sleep_ms); + } +#endif + + /* Check time events */ + te = eventLoop->timeEventHead; + maxId = eventLoop->timeEventNextId - 1; + while (te) { + long now_sec, now_ms; + jim_wide id; + + if (te->id > maxId) { + te = te->next; + continue; + } + JimGetTime(&now_sec, &now_ms); + if (now_sec > te->when_sec || (now_sec == te->when_sec && now_ms >= te->when_ms)) { + id = te->id; + /* Remove from the list before executing */ + Jim_RemoveTimeHandler(eventLoop, id); + te->timeProc(interp, te->clientData); + /* After an event is processed our time event list may + * no longer be the same, so we restart from head. + * Still we make sure to don't process events registered + * by event handlers itself in order to don't loop forever + * even in case an [after 0] that continuously register + * itself. To do so we saved the max ID we want to handle. */ + Jim_FreeTimeHandler(interp, te); + + te = eventLoop->timeEventHead; + processed++; + } + else { + te = te->next; + } + } + + return processed; +} + +/* ---------------------------------------------------------------------- */ + +static void JimELAssocDataDeleProc(Jim_Interp *interp, void *data) +{ + void *next; + Jim_FileEvent *fe; + Jim_TimeEvent *te; + Jim_EventLoop *eventLoop = data; + + fe = eventLoop->fileEventHead; + while (fe) { + next = fe->next; + if (fe->finalizerProc) + fe->finalizerProc(interp, fe->clientData); + Jim_Free(fe); + fe = next; + } + + te = eventLoop->timeEventHead; + while (te) { + next = te->next; + if (te->finalizerProc) + te->finalizerProc(interp, te->clientData); + Jim_Free(te); + te = next; + } + Jim_Free(data); +} + +static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + Jim_Obj *oldValue; + int rc; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "name"); + return JIM_ERR; + } + + oldValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE); + if (oldValue) { + Jim_IncrRefCount(oldValue); + } + else { + /* If a result was left, it is an error */ + int len; + Jim_GetString(interp->result, &len); + if (len) { + return JIM_ERR; + } + } + + eventLoop->suppress_bgerror = 0; + + while ((rc = Jim_ProcessEvents(interp, JIM_ALL_EVENTS)) >= 0) { + Jim_Obj *currValue; + currValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE); + /* Stop the loop if the vwait-ed variable changed value, + * or if was unset and now is set (or the contrary). */ + if ((oldValue && !currValue) || + (!oldValue && currValue) || + (oldValue && currValue && !Jim_StringEqObj(oldValue, currValue))) + break; + } + if (oldValue) + Jim_DecrRefCount(interp, oldValue); + + + if (rc == -2) { + return JIM_ERR; + } + + Jim_SetEmptyResult(interp); + return JIM_OK; +} + +static int JimELUpdateCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + static const char * const options[] = { + "idletasks", NULL + }; + enum { UPDATE_IDLE, UPDATE_NONE }; + int option = UPDATE_NONE; + int flags = JIM_TIME_EVENTS; + + if (argc == 1) { + flags = JIM_ALL_EVENTS; + } + else if (argc > 2 || Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + Jim_WrongNumArgs(interp, 1, argv, "?idletasks?"); + return JIM_ERR; + } + + eventLoop->suppress_bgerror = 0; + + while (Jim_ProcessEvents(interp, flags | JIM_DONT_WAIT) > 0) { + } + + return JIM_OK; +} + +static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_EvalObjBackground(interp, objPtr); +} + +static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData) +{ + Jim_Obj *objPtr = clientData; + + Jim_DecrRefCount(interp, objPtr); +} + +static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp); + jim_wide ms = 0, id; + Jim_Obj *objPtr, *idObjPtr; + static const char * const options[] = { + "cancel", "info", "idle", NULL + }; + enum + { AFTER_CANCEL, AFTER_INFO, AFTER_IDLE, AFTER_RESTART, AFTER_EXPIRE, AFTER_CREATE }; + int option = AFTER_CREATE; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arg ...?"); + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[1], &ms) != JIM_OK) { + if (Jim_GetEnum(interp, argv[1], options, &option, "argument", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_SetEmptyResult(interp); + } + else if (argc == 2) { + /* Simply a sleep */ + msleep(ms); + return JIM_OK; + } + + switch (option) { + case AFTER_IDLE: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "script ?script ...?"); + return JIM_ERR; + } + /* fall through */ + case AFTER_CREATE: { + Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2); + Jim_IncrRefCount(scriptObj); + id = Jim_CreateTimeHandler(interp, ms, JimAfterTimeHandler, scriptObj, + JimAfterTimeEventFinalizer); + objPtr = Jim_NewStringObj(interp, NULL, 0); + Jim_AppendString(interp, objPtr, "after#", -1); + idObjPtr = Jim_NewIntObj(interp, id); + Jim_IncrRefCount(idObjPtr); + Jim_AppendObj(interp, objPtr, idObjPtr); + Jim_DecrRefCount(interp, idObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + case AFTER_CANCEL: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "id|command"); + return JIM_ERR; + } + else { + jim_wide remain = 0; + + id = JimParseAfterId(argv[2]); + if (id < 0) { + /* Not an event id, so search by script */ + Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2); + id = JimFindAfterByScript(eventLoop, scriptObj); + Jim_FreeNewObj(interp, scriptObj); + if (id < 0) { + /* Not found */ + break; + } + } + remain = Jim_DeleteTimeHandler(interp, id); + if (remain >= 0) { + Jim_SetResultInt(interp, remain); + } + } + break; + + case AFTER_INFO: + if (argc == 2) { + Jim_TimeEvent *te = eventLoop->timeEventHead; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + char buf[30]; + const char *fmt = "after#%" JIM_WIDE_MODIFIER; + + while (te) { + snprintf(buf, sizeof(buf), fmt, te->id); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, buf, -1)); + te = te->next; + } + Jim_SetResult(interp, listObj); + } + else if (argc == 3) { + id = JimParseAfterId(argv[2]); + if (id >= 0) { + Jim_TimeEvent *e = JimFindTimeHandlerById(eventLoop, id); + if (e && e->timeProc == JimAfterTimeHandler) { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, e->clientData); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, e->initialms ? "timer" : "idle", -1)); + Jim_SetResult(interp, listObj); + return JIM_OK; + } + } + Jim_SetResultFormatted(interp, "event \"%#s\" doesn't exist", argv[2]); + return JIM_ERR; + } + else { + Jim_WrongNumArgs(interp, 2, argv, "?id?"); + return JIM_ERR; + } + break; + } + return JIM_OK; +} + +int Jim_eventloopInit(Jim_Interp *interp) +{ + Jim_EventLoop *eventLoop; + + if (Jim_PackageProvide(interp, "eventloop", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + eventLoop = Jim_Alloc(sizeof(*eventLoop)); + eventLoop->fileEventHead = NULL; + eventLoop->timeEventHead = NULL; + eventLoop->timeEventNextId = 1; + eventLoop->suppress_bgerror = 0; + Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop); + + Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL); + Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL); + Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h new file mode 100755 index 0000000..4da5408 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-eventloop.h @@ -0,0 +1,87 @@ +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ +/* ------ USAGE ------- + * + * In order to use this file from other extensions include it in every + * file where you need to call the eventloop API, also in the init + * function of your extension call Jim_ImportEventloopAPI(interp) + * after the Jim_InitExtension() call. + * + * See the UDP extension as example. + */ + + +#ifndef __JIM_EVENTLOOP_H__ +#define __JIM_EVENTLOOP_H__ + +#include <stdio.h> + +typedef int Jim_FileProc(Jim_Interp *interp, void *clientData, int mask); +typedef int Jim_SignalProc(Jim_Interp *interp, void *clientData, void *msg); +typedef void Jim_TimeProc(Jim_Interp *interp, void *clientData); +typedef void Jim_EventFinalizerProc(Jim_Interp *interp, void *clientData); + +/* File event structure */ +#define JIM_EVENT_READABLE 1 +#define JIM_EVENT_WRITABLE 2 +#define JIM_EVENT_EXCEPTION 4 + +JIM_EXPORT void Jim_CreateFileHandler (Jim_Interp *interp, + FILE *handle, int mask, + Jim_FileProc *proc, void *clientData, + Jim_EventFinalizerProc *finalizerProc); +JIM_EXPORT void Jim_DeleteFileHandler (Jim_Interp *interp, + FILE *handle); +JIM_EXPORT jim_wide Jim_CreateTimeHandler (Jim_Interp *interp, + jim_wide milliseconds, + Jim_TimeProc *proc, void *clientData, + Jim_EventFinalizerProc *finalizerProc); +JIM_EXPORT jim_wide Jim_DeleteTimeHandler (Jim_Interp *interp, jim_wide id); + +#define JIM_FILE_EVENTS 1 +#define JIM_TIME_EVENTS 2 +#define JIM_ALL_EVENTS (JIM_FILE_EVENTS|JIM_TIME_EVENTS) +#define JIM_DONT_WAIT 4 + +JIM_EXPORT int Jim_ProcessEvents (Jim_Interp *interp, int flags); +JIM_EXPORT int Jim_EvalObjBackground (Jim_Interp *interp, Jim_Obj *scriptObjPtr); + +int Jim_eventloopInit(Jim_Interp *interp); + +#endif /* __JIM_EVENTLOOP_H__ */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-exec.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-exec.c new file mode 100755 index 0000000..9088156 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-exec.c @@ -0,0 +1,1619 @@ +/* + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Implements the exec command for Jim + * + * Based on code originally from Tcl 6.7 by John Ousterhout. + * From that code: + * + * The Tcl_Fork and Tcl_WaitPids procedures are based on code + * contributed by Karl Lehenbauer, Mark Diekhans and Peter + * da Silva. + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <string.h> +#include <ctype.h> + +#include "jim.h" +#include "jimautoconf.h" + +#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) +/* Poor man's implementation of exec with system() + * The system() call *may* do command line redirection, etc. + * The standard output is not available. + * Can't redirect filehandles. + */ +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); + int i, j; + int rc; + + /* Create a quoted command line */ + for (i = 1; i < argc; i++) { + int len; + const char *arg = Jim_GetString(argv[i], &len); + + if (i > 1) { + Jim_AppendString(interp, cmdlineObj, " ", 1); + } + if (strpbrk(arg, "\\\" ") == NULL) { + /* No quoting required */ + Jim_AppendString(interp, cmdlineObj, arg, len); + continue; + } + + Jim_AppendString(interp, cmdlineObj, "\"", 1); + for (j = 0; j < len; j++) { + if (arg[j] == '\\' || arg[j] == '"') { + Jim_AppendString(interp, cmdlineObj, "\\", 1); + } + Jim_AppendString(interp, cmdlineObj, &arg[j], 1); + } + Jim_AppendString(interp, cmdlineObj, "\"", 1); + } + rc = system(Jim_String(cmdlineObj)); + + Jim_FreeNewObj(interp, cmdlineObj); + + if (rc) { + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc)); + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return JIM_ERR; + } + + return JIM_OK; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); + return JIM_OK; +} +#else +/* Full exec implementation for unix and mingw */ + +#include <errno.h> +#include <signal.h> + +#define XXX printf("@%s:%d\n", __FILE__, __LINE__); fflush(stdout); + +#if defined(__MINGW32__) + /* XXX: Should we use this implementation for cygwin too? */ + #include <fcntl.h> + + typedef HANDLE fdtype; + typedef HANDLE pidtype; + #define JIM_BAD_FD INVALID_HANDLE_VALUE + #define JIM_BAD_PID INVALID_HANDLE_VALUE + #define JimCloseFd CloseHandle + + #define WIFEXITED(STATUS) 1 + #define WEXITSTATUS(STATUS) (STATUS) + #define WIFSIGNALED(STATUS) 0 + #define WTERMSIG(STATUS) 0 + #define WNOHANG 1 + + static fdtype JimFileno(FILE *fh); + static pidtype JimWaitPid(pidtype pid, int *status, int nohang); + static fdtype JimDupFd(fdtype infd); + static fdtype JimOpenForRead(const char *filename); + static FILE *JimFdOpenForRead(fdtype fd); + static int JimPipe(fdtype pipefd[2]); + static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, + fdtype inputId, fdtype outputId, fdtype errorId); + static int JimErrno(void); +#else + #include "jim-signal.h" + #include <unistd.h> + #include <fcntl.h> + #include <sys/wait.h> + + typedef int fdtype; + typedef int pidtype; + #define JimPipe pipe + #define JimErrno() errno + #define JIM_BAD_FD -1 + #define JIM_BAD_PID -1 + #define JimFileno fileno + #define JimReadFd read + #define JimCloseFd close + #define JimWaitPid waitpid + #define JimDupFd dup + #define JimFdOpenForRead(FD) fdopen((FD), "r") + #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0) +#endif + +static const char *JimStrError(void); +static char **JimSaveEnv(char **env); +static void JimRestoreEnv(char **env); +static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, + pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId); +static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents); +static fdtype JimOpenForWrite(const char *filename, int append); +static int JimRewindFd(fdtype fd); + +static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) +{ + Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError()); +} + +static const char *JimStrError(void) +{ + return strerror(JimErrno()); +} + +static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) +{ + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } +} + +/** + * Read from 'fd', append the data to strObj and close 'fd'. + * Returns JIM_OK if OK, or JIM_ERR on error. + */ +static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj) +{ + char buf[256]; + FILE *fh = JimFdOpenForRead(fd); + if (fh == NULL) { + return JIM_ERR; + } + + while (1) { + int retval = fread(buf, 1, sizeof(buf), fh); + if (retval > 0) { + Jim_AppendString(interp, strObj, buf, retval); + } + if (retval != sizeof(buf)) { + break; + } + } + Jim_RemoveTrailingNewline(strObj); + fclose(fh); + return JIM_OK; +} + +/* + * If the last character of the result is a newline, then remove + * the newline character (the newline would just confuse things). + * + * Note: Ideally we could do this by just reducing the length of stringrep + * by 1, but there is no API for this :-( + */ +static void JimTrimTrailingNewline(Jim_Interp *interp) +{ + int len; + const char *p = Jim_GetString(Jim_GetResult(interp), &len); + + if (len > 0 && p[len - 1] == '\n') { + Jim_SetResultString(interp, p, len - 1); + } +} + +/** + * Builds the environment array from $::env + * + * If $::env is not set, simply returns environ. + * + * Otherwise allocates the environ array from the contents of $::env + * + * If the exec fails, memory can be freed via JimFreeEnv() + */ +static char **JimBuildEnv(Jim_Interp *interp) +{ +#if defined(jim_ext_tclcompat) + int i; + int size; + int num; + int n; + char **envptr; + char *envdata; + + Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); + + if (!objPtr) { + return Jim_GetEnviron(); + } + + /* We build the array as a single block consisting of the pointers followed by + * the strings. This has the advantage of being easy to allocate/free and being + * compatible with both unix and windows + */ + + /* Calculate the required size */ + num = Jim_ListLength(interp, objPtr); + if (num % 2) { + num--; + } + size = Jim_Length(objPtr); + /* We need one \0 and one equal sign for each element. + * A list has at least one space for each element except the first. + * We only need one extra char for the extra null terminator. + */ + size++; + + envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); + envdata = (char *)&envptr[num / 2 + 1]; + + n = 0; + for (i = 0; i < num; i += 2) { + const char *s1, *s2; + Jim_Obj *elemObj; + + Jim_ListIndex(interp, objPtr, i, &elemObj, JIM_NONE); + s1 = Jim_String(elemObj); + Jim_ListIndex(interp, objPtr, i + 1, &elemObj, JIM_NONE); + s2 = Jim_String(elemObj); + + envptr[n] = envdata; + envdata += sprintf(envdata, "%s=%s", s1, s2); + envdata++; + n++; + } + envptr[n] = NULL; + *envdata = 0; + + return envptr; +#else + return Jim_GetEnviron(); +#endif +} + +/** + * Frees the environment allocated by JimBuildEnv() + * + * Must pass original_environ. + */ +static void JimFreeEnv(char **env, char **original_environ) +{ +#ifdef jim_ext_tclcompat + if (env != original_environ) { + Jim_Free(env); + } +#endif +} + +/* + * Create error messages for unusual process exits. An + * extra newline gets appended to each error message, but + * it gets removed below (in the same fashion that an + * extra newline in the command's output is removed). + */ +static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) +{ + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + int rc = JIM_ERR; + + if (WIFEXITED(waitStatus)) { + if (WEXITSTATUS(waitStatus) == 0) { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); + rc = JIM_OK; + } + else { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); + } + } + else { + const char *type; + const char *action; + + if (WIFSIGNALED(waitStatus)) { + type = "CHILDKILLED"; + action = "killed"; + } + else { + type = "CHILDSUSP"; + action = "suspended"; + } + + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); + +#ifdef jim_ext_signal + Jim_SetResultFormatted(interp, "child %s by signal %s", action, Jim_SignalId(WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1)); +#else + Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); +#endif + } + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return rc; +} + +/* + * Data structures of the following type are used by JimFork and + * JimWaitPids to keep track of child processes. + */ + +struct WaitInfo +{ + pidtype pid; /* Process id of child. */ + int status; /* Status returned when child exited or suspended. */ + int flags; /* Various flag bits; see below for definitions. */ +}; + +struct WaitInfoTable { + struct WaitInfo *info; + int size; + int used; +}; + +/* + * Flag bits in WaitInfo structures: + * + * WI_DETACHED - Non-zero means no-one cares about the + * process anymore. Ignore it until it + * exits, then forget about it. + */ + +#define WI_DETACHED 2 + +#define WAIT_TABLE_GROW_BY 4 + +static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) +{ + struct WaitInfoTable *table = privData; + + Jim_Free(table->info); + Jim_Free(table); +} + +static struct WaitInfoTable *JimAllocWaitInfoTable(void) +{ + struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); + table->info = NULL; + table->size = table->used = 0; + + return table; +} + +/* + * The main [exec] command + */ +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + fdtype outputId; /* File id for output pipe. -1 + * means command overrode. */ + fdtype errorId; /* File id for temporary file + * containing error output. */ + pidtype *pidPtr; + int numPids, result; + + /* + * See if the command is to be run in background; if so, create + * the command, detach it, and return. + */ + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { + Jim_Obj *listObj; + int i; + + argc--; + numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); + if (numPids < 0) { + return JIM_ERR; + } + /* The return value is a list of the pids */ + listObj = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < numPids; i++) { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); + } + Jim_SetResult(interp, listObj); + JimDetachPids(interp, numPids, pidPtr); + Jim_Free(pidPtr); + return JIM_OK; + } + + /* + * Create the command's pipeline. + */ + numPids = + JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId); + + if (numPids < 0) { + return JIM_ERR; + } + + /* + * Read the child's output (if any) and put it into the result. + */ + Jim_SetResultString(interp, "", 0); + + result = JIM_OK; + if (outputId != JIM_BAD_FD) { + result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp)); + if (result < 0) { + Jim_SetResultErrno(interp, "error reading from output pipe"); + } + } + + if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) { + result = JIM_ERR; + } + return result; +} + +static void JimReapDetachedPids(struct WaitInfoTable *table) +{ + struct WaitInfo *waitPtr; + int count; + + if (!table) { + return; + } + + for (waitPtr = table->info, count = table->used; count > 0; waitPtr++, count--) { + if (waitPtr->flags & WI_DETACHED) { + int status; + pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); + if (pid != JIM_BAD_PID) { + if (waitPtr != &table->info[table->used - 1]) { + *waitPtr = table->info[table->used - 1]; + } + table->used--; + } + } + } +} + +/** + * Does waitpid() on the given pid, and then removes the + * entry from the wait table. + * + * Returns the pid if OK and updates *statusPtr with the status, + * or JIM_BAD_PID if the pid was not in the table. + */ +static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) +{ + int i; + + /* Find it in the table */ + for (i = 0; i < table->used; i++) { + if (pid == table->info[i].pid) { + /* wait for it */ + JimWaitPid(pid, statusPtr, 0); + + /* Remove it from the table */ + if (i != table->used - 1) { + table->info[i] = table->info[table->used - 1]; + } + table->used--; + return pid; + } + } + + /* Not found */ + return JIM_BAD_PID; +} + +/* + *---------------------------------------------------------------------- + * + * JimDetachPids -- + * + * This procedure is called to indicate that one or more child + * processes have been placed in background and are no longer + * cared about. These children can be cleaned up with JimReapDetachedPids(). + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) +{ + int j; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + for (j = 0; j < numPids; j++) { + /* Find it in the table */ + int i; + for (i = 0; i < table->used; i++) { + if (pidPtr[j] == table->info[i].pid) { + table->info[i].flags |= WI_DETACHED; + break; + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * JimCreatePipeline -- + * + * Given an argc/argv array, instantiate a pipeline of processes + * as described by the argv. + * + * Results: + * The return value is a count of the number of new processes + * created, or -1 if an error occurred while creating the pipeline. + * *pidArrayPtr is filled in with the address of a dynamically + * allocated array giving the ids of all of the processes. It + * is up to the caller to free this array when it isn't needed + * anymore. If inPipePtr is non-NULL, *inPipePtr is filled in + * with the file id for the input pipe for the pipeline (if any): + * the caller must eventually close this file. If outPipePtr + * isn't NULL, then *outPipePtr is filled in with the file id + * for the output pipe from the pipeline: the caller must close + * this file. If errFilePtr isn't NULL, then *errFilePtr is filled + * with a file id that may be used to read error output after the + * pipeline completes. + * + * Side effects: + * Processes and pipes are created. + * + *---------------------------------------------------------------------- + */ +static int +JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, + fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr) +{ + pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all + * the pids of child processes. */ + int numPids = 0; /* Actual number of processes that exist + * at *pidPtr right now. */ + int cmdCount; /* Count of number of distinct commands + * found in argc/argv. */ + const char *input = NULL; /* Describes input for pipeline, depending + * on "inputFile". NULL means take input + * from stdin/pipe. */ + +#define FILE_NAME 0 /* input/output: filename */ +#define FILE_APPEND 1 /* output only: filename, append */ +#define FILE_HANDLE 2 /* input/output: filehandle */ +#define FILE_TEXT 3 /* input only: input is actual text */ + + int inputFile = FILE_NAME; /* 1 means input is name of input file. + * 2 means input is filehandle name. + * 0 means input holds actual + * text to be input to command. */ + + int outputFile = FILE_NAME; /* 0 means output is the name of output file. + * 1 means output is the name of output file, and append. + * 2 means output is filehandle name. + * All this is ignored if output is NULL + */ + int errorFile = FILE_NAME; /* 0 means error is the name of error file. + * 1 means error is the name of error file, and append. + * 2 means error is filehandle name. + * All this is ignored if error is NULL + */ + const char *output = NULL; /* Holds name of output file to pipe to, + * or NULL if output goes to stdout/pipe. */ + const char *error = NULL; /* Holds name of stderr file to pipe to, + * or NULL if stderr goes to stderr/pipe. */ + fdtype inputId = JIM_BAD_FD; + /* Readable file id input to current command in + * pipeline (could be file or pipe). JIM_BAD_FD + * means use stdin. */ + fdtype outputId = JIM_BAD_FD; + /* Writable file id for output from current + * command in pipeline (could be file or pipe). + * JIM_BAD_FD means use stdout. */ + fdtype errorId = JIM_BAD_FD; + /* Writable file id for all standard error + * output from all commands in pipeline. JIM_BAD_FD + * means use stderr. */ + fdtype lastOutputId = JIM_BAD_FD; + /* Write file id for output from last command + * in pipeline (could be file or pipe). + * -1 means use stdout. */ + fdtype pipeIds[2]; /* File ids for pipe that's being created. */ + int firstArg, lastArg; /* Indexes of first and last arguments in + * current command. */ + int lastBar; + int i; + pidtype pid; + char **save_environ; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + /* Holds the args which will be used to exec */ + char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); + int arg_count = 0; + + JimReapDetachedPids(table); + + if (inPipePtr != NULL) { + *inPipePtr = JIM_BAD_FD; + } + if (outPipePtr != NULL) { + *outPipePtr = JIM_BAD_FD; + } + if (errFilePtr != NULL) { + *errFilePtr = JIM_BAD_FD; + } + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + + /* + * First, scan through all the arguments to figure out the structure + * of the pipeline. Count the number of distinct processes (it's the + * number of "|" arguments). If there are "<", "<<", or ">" arguments + * then make note of input and output redirection and remove these + * arguments and the arguments that follow them. + */ + cmdCount = 1; + lastBar = -1; + for (i = 0; i < argc; i++) { + const char *arg = Jim_String(argv[i]); + + if (arg[0] == '<') { + inputFile = FILE_NAME; + input = arg + 1; + if (*input == '<') { + inputFile = FILE_TEXT; + input++; + } + else if (*input == '@') { + inputFile = FILE_HANDLE; + input++; + } + + if (!*input && ++i < argc) { + input = Jim_String(argv[i]); + } + } + else if (arg[0] == '>') { + int dup_error = 0; + + outputFile = FILE_NAME; + + output = arg + 1; + if (*output == '>') { + outputFile = FILE_APPEND; + output++; + } + if (*output == '&') { + /* Redirect stderr too */ + output++; + dup_error = 1; + } + if (*output == '@') { + outputFile = FILE_HANDLE; + output++; + } + if (!*output && ++i < argc) { + output = Jim_String(argv[i]); + } + if (dup_error) { + errorFile = outputFile; + error = output; + } + } + else if (arg[0] == '2' && arg[1] == '>') { + error = arg + 2; + errorFile = FILE_NAME; + + if (*error == '@') { + errorFile = FILE_HANDLE; + error++; + } + else if (*error == '>') { + errorFile = FILE_APPEND; + error++; + } + if (!*error && ++i < argc) { + error = Jim_String(argv[i]); + } + } + else { + if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) { + if (i == lastBar + 1 || i == argc - 1) { + Jim_SetResultString(interp, "illegal use of | or |& in command", -1); + goto badargs; + } + lastBar = i; + cmdCount++; + } + /* Either |, |& or a "normal" arg, so store it in the arg array */ + arg_array[arg_count++] = (char *)arg; + continue; + } + + if (i >= argc) { + Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg); + goto badargs; + } + } + + if (arg_count == 0) { + Jim_SetResultString(interp, "didn't specify command to execute", -1); +badargs: + Jim_Free(arg_array); + return -1; + } + + /* Must do this before vfork(), so do it now */ + save_environ = JimSaveEnv(JimBuildEnv(interp)); + + /* + * Set up the redirected input source for the pipeline, if + * so requested. + */ + if (input != NULL) { + if (inputFile == FILE_TEXT) { + /* + * Immediate data in command. Create temporary file and + * put data into file. + */ + inputId = JimCreateTemp(interp, input); + if (inputId == JIM_BAD_FD) { + goto error; + } + } + else if (inputFile == FILE_HANDLE) { + /* Should be a file descriptor */ + Jim_Obj *fhObj = Jim_NewStringObj(interp, input, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + inputId = JimDupFd(JimFileno(fh)); + } + else { + /* + * File redirection. Just open the file. + */ + inputId = JimOpenForRead(input); + if (inputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError()); + goto error; + } + } + } + else if (inPipePtr != NULL) { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create input pipe for command"); + goto error; + } + inputId = pipeIds[0]; + *inPipePtr = pipeIds[1]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + + /* + * Set up the redirected output sink for the pipeline from one + * of two places, if requested. + */ + if (output != NULL) { + if (outputFile == FILE_HANDLE) { + Jim_Obj *fhObj = Jim_NewStringObj(interp, output, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + fflush(fh); + lastOutputId = JimDupFd(JimFileno(fh)); + } + else { + /* + * Output is to go to a file. + */ + lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND); + if (lastOutputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError()); + goto error; + } + } + } + else if (outPipePtr != NULL) { + /* + * Output is to go to a pipe. + */ + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create output pipe"); + goto error; + } + lastOutputId = pipeIds[1]; + *outPipePtr = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + /* If we are redirecting stderr with 2>filename or 2>@fileId, then we ignore errFilePtr */ + if (error != NULL) { + if (errorFile == FILE_HANDLE) { + if (strcmp(error, "1") == 0) { + /* Special 2>@1 */ + if (lastOutputId != JIM_BAD_FD) { + errorId = JimDupFd(lastOutputId); + } + else { + /* No redirection of stdout, so just use 2>@stdout */ + error = "stdout"; + } + } + if (errorId == JIM_BAD_FD) { + Jim_Obj *fhObj = Jim_NewStringObj(interp, error, -1); + FILE *fh = Jim_AioFilehandle(interp, fhObj); + + Jim_FreeNewObj(interp, fhObj); + if (fh == NULL) { + goto error; + } + fflush(fh); + errorId = JimDupFd(JimFileno(fh)); + } + } + else { + /* + * Output is to go to a file. + */ + errorId = JimOpenForWrite(error, errorFile == FILE_APPEND); + if (errorId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError()); + goto error; + } + } + } + else if (errFilePtr != NULL) { + /* + * Set up the standard error output sink for the pipeline, if + * requested. Use a temporary file which is opened, then deleted. + * Could potentially just use pipe, but if it filled up it could + * cause the pipeline to deadlock: we'd be waiting for processes + * to complete before reading stderr, and processes couldn't complete + * because stderr was backed up. + */ + errorId = JimCreateTemp(interp, NULL); + if (errorId == JIM_BAD_FD) { + goto error; + } + *errFilePtr = JimDupFd(errorId); + } + + /* + * Scan through the argc array, forking off a process for each + * group of arguments between "|" arguments. + */ + + pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); + for (i = 0; i < numPids; i++) { + pidPtr[i] = JIM_BAD_PID; + } + for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { + int pipe_dup_err = 0; + fdtype origErrorId = errorId; + + for (lastArg = firstArg; lastArg < arg_count; lastArg++) { + if (arg_array[lastArg][0] == '|') { + if (arg_array[lastArg][1] == '&') { + pipe_dup_err = 1; + } + break; + } + } + /* Replace | with NULL for execv() */ + arg_array[lastArg] = NULL; + if (lastArg == arg_count) { + outputId = lastOutputId; + } + else { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create pipe"); + goto error; + } + outputId = pipeIds[1]; + } + + /* Now fork the child */ + +#ifdef __MINGW32__ + pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); + if (pid == JIM_BAD_PID) { + Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); + goto error; + } +#else + /* + * Disable SIGPIPE signals: if they were allowed, this process + * might go away unexpectedly if children misbehave. This code + * can potentially interfere with other application code that + * expects to handle SIGPIPEs; what's really needed is an + * arbiter for signals to allow them to be "shared". + */ + if (table->info == NULL) { + (void)signal(SIGPIPE, SIG_IGN); + } + + /* Need to do this befor vfork() */ + if (pipe_dup_err) { + errorId = outputId; + } + + /* + * Make a new process and enter it into the table if the fork + * is successful. + */ + pid = vfork(); + if (pid < 0) { + Jim_SetResultErrno(interp, "couldn't fork child process"); + goto error; + } + if (pid == 0) { + /* Child */ + + if (inputId != -1) dup2(inputId, 0); + if (outputId != -1) dup2(outputId, 1); + if (errorId != -1) dup2(errorId, 2); + + for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { + close(i); + } + + execvp(arg_array[firstArg], &arg_array[firstArg]); + + /* Need to prep an error message before vfork(), just in case */ + fprintf(stderr, "couldn't exec \"%s\"", arg_array[firstArg]); + _exit(127); + } +#endif + + /* parent */ + + /* + * Enlarge the wait table if there isn't enough space for a new + * entry. + */ + if (table->used == table->size) { + table->size += WAIT_TABLE_GROW_BY; + table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); + } + + table->info[table->used].pid = pid; + table->info[table->used].flags = 0; + table->used++; + + pidPtr[numPids] = pid; + + /* Restore in case of pipe_dup_err */ + errorId = origErrorId; + + /* + * Close off our copies of file descriptors that were set up for + * this child, then set up the input for the next child. + */ + + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (outputId != JIM_BAD_FD) { + JimCloseFd(outputId); + } + inputId = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + *pidArrayPtr = pidPtr; + + /* + * All done. Cleanup open files lying around and then return. + */ + + cleanup: + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (lastOutputId != JIM_BAD_FD) { + JimCloseFd(lastOutputId); + } + if (errorId != JIM_BAD_FD) { + JimCloseFd(errorId); + } + Jim_Free(arg_array); + + JimRestoreEnv(save_environ); + + return numPids; + + /* + * An error occurred. There could have been extra files open, such + * as pipes between children. Clean them all up. Detach any child + * processes that have been created. + */ + + error: + if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) { + JimCloseFd(*inPipePtr); + *inPipePtr = JIM_BAD_FD; + } + if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) { + JimCloseFd(*outPipePtr); + *outPipePtr = JIM_BAD_FD; + } + if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) { + JimCloseFd(*errFilePtr); + *errFilePtr = JIM_BAD_FD; + } + if (pipeIds[0] != JIM_BAD_FD) { + JimCloseFd(pipeIds[0]); + } + if (pipeIds[1] != JIM_BAD_FD) { + JimCloseFd(pipeIds[1]); + } + if (pidPtr != NULL) { + for (i = 0; i < numPids; i++) { + if (pidPtr[i] != JIM_BAD_PID) { + JimDetachPids(interp, 1, &pidPtr[i]); + } + } + Jim_Free(pidPtr); + } + numPids = -1; + goto cleanup; +} + +/* + *---------------------------------------------------------------------- + * + * JimCleanupChildren -- + * + * This is a utility procedure used to wait for child processes + * to exit, record information about abnormal exits, and then + * collect any stderr output generated by them. + * + * Results: + * The return value is a standard Tcl result. If anything at + * weird happened with the child processes, JIM_ERROR is returned + * and a message is left in interp->result. + * + * Side effects: + * If the last character of interp->result is a newline, then it + * is removed. File errorId gets closed, and pidPtr is freed + * back to the storage allocator. + * + *---------------------------------------------------------------------- + */ + +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId) +{ + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + int result = JIM_OK; + int i; + + for (i = 0; i < numPids; i++) { + int waitStatus = 0; + if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { + if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) { + result = JIM_ERR; + } + } + } + Jim_Free(pidPtr); + + /* + * Read the standard error file. If there's anything there, + * then add the file's contents to the result + * string. + */ + if (errorId != JIM_BAD_FD) { + JimRewindFd(errorId); + if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { + result = JIM_ERR; + } + } + + JimTrimTrailingNewline(interp); + + return result; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); + return JIM_OK; +} + +#if defined(__MINGW32__) +/* Windows-specific (mingw) implementation */ + +static SECURITY_ATTRIBUTES *JimStdSecAttrs(void) +{ + static SECURITY_ATTRIBUTES secAtts; + + secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); + secAtts.lpSecurityDescriptor = NULL; + secAtts.bInheritHandle = TRUE; + return &secAtts; +} + +static int JimErrno(void) +{ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: return ENOENT; + case ERROR_PATH_NOT_FOUND: return ENOENT; + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; + case ERROR_ACCESS_DENIED: return EACCES; + case ERROR_INVALID_HANDLE: return EBADF; + case ERROR_BAD_ENVIRONMENT: return E2BIG; + case ERROR_BAD_FORMAT: return ENOEXEC; + case ERROR_INVALID_ACCESS: return EACCES; + case ERROR_INVALID_DRIVE: return ENOENT; + case ERROR_CURRENT_DIRECTORY: return EACCES; + case ERROR_NOT_SAME_DEVICE: return EXDEV; + case ERROR_NO_MORE_FILES: return ENOENT; + case ERROR_WRITE_PROTECT: return EROFS; + case ERROR_BAD_UNIT: return ENXIO; + case ERROR_NOT_READY: return EBUSY; + case ERROR_BAD_COMMAND: return EIO; + case ERROR_CRC: return EIO; + case ERROR_BAD_LENGTH: return EIO; + case ERROR_SEEK: return EIO; + case ERROR_WRITE_FAULT: return EIO; + case ERROR_READ_FAULT: return EIO; + case ERROR_GEN_FAILURE: return EIO; + case ERROR_SHARING_VIOLATION: return EACCES; + case ERROR_LOCK_VIOLATION: return EACCES; + case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; + case ERROR_HANDLE_DISK_FULL: return ENOSPC; + case ERROR_NOT_SUPPORTED: return ENODEV; + case ERROR_REM_NOT_LIST: return EBUSY; + case ERROR_DUP_NAME: return EEXIST; + case ERROR_BAD_NETPATH: return ENOENT; + case ERROR_NETWORK_BUSY: return EBUSY; + case ERROR_DEV_NOT_EXIST: return ENODEV; + case ERROR_TOO_MANY_CMDS: return EAGAIN; + case ERROR_ADAP_HDW_ERR: return EIO; + case ERROR_BAD_NET_RESP: return EIO; + case ERROR_UNEXP_NET_ERR: return EIO; + case ERROR_NETNAME_DELETED: return ENOENT; + case ERROR_NETWORK_ACCESS_DENIED: return EACCES; + case ERROR_BAD_DEV_TYPE: return ENODEV; + case ERROR_BAD_NET_NAME: return ENOENT; + case ERROR_TOO_MANY_NAMES: return ENFILE; + case ERROR_TOO_MANY_SESS: return EIO; + case ERROR_SHARING_PAUSED: return EAGAIN; + case ERROR_REDIR_PAUSED: return EAGAIN; + case ERROR_FILE_EXISTS: return EEXIST; + case ERROR_CANNOT_MAKE: return ENOSPC; + case ERROR_OUT_OF_STRUCTURES: return ENFILE; + case ERROR_ALREADY_ASSIGNED: return EEXIST; + case ERROR_INVALID_PASSWORD: return EPERM; + case ERROR_NET_WRITE_FAULT: return EIO; + case ERROR_NO_PROC_SLOTS: return EAGAIN; + case ERROR_DISK_CHANGE: return EXDEV; + case ERROR_BROKEN_PIPE: return EPIPE; + case ERROR_OPEN_FAILED: return ENOENT; + case ERROR_DISK_FULL: return ENOSPC; + case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; + case ERROR_INVALID_TARGET_HANDLE: return EBADF; + case ERROR_INVALID_NAME: return ENOENT; + case ERROR_PROC_NOT_FOUND: return ESRCH; + case ERROR_WAIT_NO_CHILDREN: return ECHILD; + case ERROR_CHILD_NOT_COMPLETE: return ECHILD; + case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; + case ERROR_SEEK_ON_DEVICE: return ESPIPE; + case ERROR_BUSY_DRIVE: return EAGAIN; + case ERROR_DIR_NOT_EMPTY: return EEXIST; + case ERROR_NOT_LOCKED: return EACCES; + case ERROR_BAD_PATHNAME: return ENOENT; + case ERROR_LOCK_FAILED: return EACCES; + case ERROR_ALREADY_EXISTS: return EEXIST; + case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; + case ERROR_BAD_PIPE: return EPIPE; + case ERROR_PIPE_BUSY: return EAGAIN; + case ERROR_PIPE_NOT_CONNECTED: return EPIPE; + case ERROR_DIRECTORY: return ENOTDIR; + } + return EINVAL; +} + +static int JimPipe(fdtype pipefd[2]) +{ + if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) { + return 0; + } + return -1; +} + +static fdtype JimDupFd(fdtype infd) +{ + fdtype dupfd; + pidtype pid = GetCurrentProcess(); + + if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + return dupfd; + } + return JIM_BAD_FD; +} + +static int JimRewindFd(fdtype fd) +{ + return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0; +} + +#if 0 +static int JimReadFd(fdtype fd, char *buffer, size_t len) +{ + DWORD num; + + if (ReadFile(fd, buffer, len, &num, NULL)) { + return num; + } + if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) { + return 0; + } + return -1; +} +#endif + +static FILE *JimFdOpenForRead(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r"); +} + +static fdtype JimFileno(FILE *fh) +{ + return (fdtype)_get_osfhandle(_fileno(fh)); +} + +static fdtype JimOpenForRead(const char *filename) +{ + return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), OPEN_EXISTING, 0, NULL); +} + +static fdtype JimOpenForWrite(const char *filename, int append) +{ + return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL); +} + +static FILE *JimFdOpenForWrite(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w"); +} + +static pidtype JimWaitPid(pidtype pid, int *status, int nohang) +{ + DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { + /* WAIT_TIMEOUT can only happend with WNOHANG */ + return JIM_BAD_PID; + } + GetExitCodeProcess(pid, &ret); + *status = ret; + CloseHandle(pid); + return pid; +} + +static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents) +{ + char name[MAX_PATH]; + HANDLE handle; + + if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { + return JIM_BAD_FD; + } + + handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(), + CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (handle == INVALID_HANDLE_VALUE) { + goto error; + } + + if (contents != NULL) { + /* Use fdopen() to get automatic text-mode translation */ + FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); + if (fh == NULL) { + goto error; + } + + if (fwrite(contents, strlen(contents), 1, fh) != 1) { + fclose(fh); + goto error; + } + fseek(fh, 0, SEEK_SET); + fclose(fh); + } + return handle; + + error: + Jim_SetResultErrno(interp, "failed to create temp file"); + CloseHandle(handle); + DeleteFile(name); + return JIM_BAD_FD; +} + +static int +JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) +{ + int i; + static char extensions[][5] = {".exe", "", ".bat"}; + + for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { + lstrcpyn(fullPath, originalName, MAX_PATH - 5); + lstrcat(fullPath, extensions[i]); + + if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) { + continue; + } + if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) { + continue; + } + return 0; + } + + return -1; +} + +static char **JimSaveEnv(char **env) +{ + return env; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(env, NULL); +} + +static Jim_Obj * +JimWinBuildCommandLine(Jim_Interp *interp, char **argv) +{ + char *start, *special; + int quote, i; + + Jim_Obj *strObj = Jim_NewStringObj(interp, "", 0); + + for (i = 0; argv[i]; i++) { + if (i > 0) { + Jim_AppendString(interp, strObj, " ", 1); + } + + if (argv[i][0] == '\0') { + quote = 1; + } + else { + quote = 0; + for (start = argv[i]; *start != '\0'; start++) { + if (isspace(UCHAR(*start))) { + quote = 1; + break; + } + } + } + if (quote) { + Jim_AppendString(interp, strObj, "\"" , 1); + } + + start = argv[i]; + for (special = argv[i]; ; ) { + if ((*special == '\\') && (special[1] == '\\' || + special[1] == '"' || (quote && special[1] == '\0'))) { + Jim_AppendString(interp, strObj, start, special - start); + start = special; + while (1) { + special++; + if (*special == '"' || (quote && *special == '\0')) { + /* + * N backslashes followed a quote -> insert + * N * 2 + 1 backslashes then a quote. + */ + + Jim_AppendString(interp, strObj, start, special - start); + break; + } + if (*special != '\\') { + break; + } + } + Jim_AppendString(interp, strObj, start, special - start); + start = special; + } + if (*special == '"') { + if (special == start) { + Jim_AppendString(interp, strObj, "\"", 1); + } + else { + Jim_AppendString(interp, strObj, start, special - start); + } + Jim_AppendString(interp, strObj, "\\\"", 2); + start = special + 1; + } + if (*special == '\0') { + break; + } + special++; + } + Jim_AppendString(interp, strObj, start, special - start); + if (quote) { + Jim_AppendString(interp, strObj, "\"", 1); + } + } + return strObj; +} + +static pidtype +JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId) +{ + STARTUPINFO startInfo; + PROCESS_INFORMATION procInfo; + HANDLE hProcess, h; + char execPath[MAX_PATH]; + char *originalName; + pidtype pid = JIM_BAD_PID; + Jim_Obj *cmdLineObj; + + if (JimWinFindExecutable(argv[0], execPath) < 0) { + return JIM_BAD_PID; + } + originalName = argv[0]; + argv[0] = execPath; + + hProcess = GetCurrentProcess(); + cmdLineObj = JimWinBuildCommandLine(interp, argv); + + /* + * STARTF_USESTDHANDLES must be used to pass handles to child process. + * Using SetStdHandle() and/or dup2() only works when a console mode + * parent process is spawning an attached console mode child process. + */ + + ZeroMemory(&startInfo, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); + startInfo.dwFlags = STARTF_USESTDHANDLES; + startInfo.hStdInput = INVALID_HANDLE_VALUE; + startInfo.hStdOutput= INVALID_HANDLE_VALUE; + startInfo.hStdError = INVALID_HANDLE_VALUE; + + /* + * Duplicate all the handles which will be passed off as stdin, stdout + * and stderr of the child process. The duplicate handles are set to + * be inheritable, so the child process can use them. + */ + if (inputId == JIM_BAD_FD) { + if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { + CloseHandle(h); + } + } else { + DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdInput == JIM_BAD_FD) { + goto end; + } + + if (outputId == JIM_BAD_FD) { + startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdOutput == JIM_BAD_FD) { + goto end; + } + + if (errorId == JIM_BAD_FD) { + /* + * If handle was not set, errors should be sent to an infinitely + * deep sink. + */ + + startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdError == JIM_BAD_FD) { + goto end; + } + + if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, + 0, env, NULL, &startInfo, &procInfo)) { + goto end; + } + + /* + * "When an application spawns a process repeatedly, a new thread + * instance will be created for each process but the previous + * instances may not be cleaned up. This results in a significant + * virtual memory loss each time the process is spawned. If there + * is a WaitForInputIdle() call between CreateProcess() and + * CloseHandle(), the problem does not occur." PSS ID Number: Q124121 + */ + + WaitForInputIdle(procInfo.hProcess, 5000); + CloseHandle(procInfo.hThread); + + pid = procInfo.hProcess; + + end: + Jim_FreeNewObj(interp, cmdLineObj); + if (startInfo.hStdInput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdInput); + } + if (startInfo.hStdOutput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdOutput); + } + if (startInfo.hStdError != JIM_BAD_FD) { + CloseHandle(startInfo.hStdError); + } + return pid; +} +#else +/* Unix-specific implementation */ +static int JimOpenForWrite(const char *filename, int append) +{ + return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); +} + +static int JimRewindFd(int fd) +{ + return lseek(fd, 0L, SEEK_SET); +} + +static int JimCreateTemp(Jim_Interp *interp, const char *contents) +{ + char inName[] = "/tmp/tcl.tmp.XXXXXX"; + + int fd = mkstemp(inName); + if (fd == JIM_BAD_FD) { + Jim_SetResultErrno(interp, "couldn't create temp file"); + return -1; + } + unlink(inName); + if (contents) { + int length = strlen(contents); + if (write(fd, contents, length) != length) { + Jim_SetResultErrno(interp, "couldn't write temp file"); + close(fd); + return -1; + } + lseek(fd, 0L, SEEK_SET); + } + return fd; +} + +static char **JimSaveEnv(char **env) +{ + char **saveenv = Jim_GetEnviron(); + Jim_SetEnviron(env); + return saveenv; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(Jim_GetEnviron(), env); + Jim_SetEnviron(env); +} +#endif +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-file.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-file.c new file mode 100755 index 0000000..7b48368 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-file.c @@ -0,0 +1,929 @@ +/* + * Implements the file command for jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +# ifndef MAXPATHLEN +# define MAXPATHLEN JIM_PATH_LEN +# endif + +/* + *---------------------------------------------------------------------- + * + * JimGetFileType -- + * + * Given a mode word, returns a string identifying the type of a + * file. + * + * Results: + * A static text string giving the file type from mode. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static const char *JimGetFileType(int mode) +{ + if (S_ISREG(mode)) { + return "file"; + } + else if (S_ISDIR(mode)) { + return "directory"; + } + else if (S_ISCHR(mode)) { + return "characterSpecial"; + } + else if (S_ISBLK(mode)) { + return "blockSpecial"; + } + else if (S_ISFIFO(mode)) { + return "fifo"; +#ifdef S_ISLNK + } + else if (S_ISLNK(mode)) { + return "link"; +#endif +#ifdef S_ISSOCK + } + else if (S_ISSOCK(mode)) { + return "socket"; +#endif + } + return "unknown"; +} + +/* + *---------------------------------------------------------------------- + * + * StoreStatData -- + * + * This is a utility procedure that breaks out the fields of a + * "stat" structure and stores them in textual form into the + * elements of an associative array. + * + * Results: + * Returns a standard Tcl return value. If an error occurs then + * a message is left in interp->result. + * + * Side effects: + * Elements of the associative array given by "varName" are modified. + * + *---------------------------------------------------------------------- + */ + +static int set_array_int_value(Jim_Interp *interp, Jim_Obj *container, const char *key, + jim_wide value) +{ + Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); + Jim_Obj *valobj = Jim_NewWideObj(interp, value); + + if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { + Jim_FreeObj(interp, nameobj); + Jim_FreeObj(interp, valobj); + return JIM_ERR; + } + return JIM_OK; +} + +static int set_array_string_value(Jim_Interp *interp, Jim_Obj *container, const char *key, + const char *value) +{ + Jim_Obj *nameobj = Jim_NewStringObj(interp, key, -1); + Jim_Obj *valobj = Jim_NewStringObj(interp, value, -1); + + if (Jim_SetDictKeysVector(interp, container, &nameobj, 1, valobj, JIM_ERRMSG) != JIM_OK) { + Jim_FreeObj(interp, nameobj); + Jim_FreeObj(interp, valobj); + return JIM_ERR; + } + return JIM_OK; +} + +static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) +{ + if (set_array_int_value(interp, varName, "dev", sb->st_dev) != JIM_OK) { + Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variables isn't array", varName); + return JIM_ERR; + } + set_array_int_value(interp, varName, "ino", sb->st_ino); + set_array_int_value(interp, varName, "mode", sb->st_mode); + set_array_int_value(interp, varName, "nlink", sb->st_nlink); + set_array_int_value(interp, varName, "uid", sb->st_uid); + set_array_int_value(interp, varName, "gid", sb->st_gid); + set_array_int_value(interp, varName, "size", sb->st_size); + set_array_int_value(interp, varName, "atime", sb->st_atime); + set_array_int_value(interp, varName, "mtime", sb->st_mtime); + set_array_int_value(interp, varName, "ctime", sb->st_ctime); + set_array_string_value(interp, varName, "type", JimGetFileType((int)sb->st_mode)); + + /* And also return the value */ + Jim_SetResult(interp, Jim_GetVariable(interp, varName, 0)); + + return JIM_OK; +} + +static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *p = strrchr(path, '/'); + + if (!p) { + Jim_SetResultString(interp, ".", -1); + } + else if (p == path) { + Jim_SetResultString(interp, "/", -1); + } +#if defined(__MINGW32__) + else if (p[-1] == ':') { + /* z:/dir => z:/ */ + Jim_SetResultString(interp, path, p - path + 1); + } +#endif + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash > p)) { + Jim_SetResult(interp, argv[0]); + } + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash >= p)) { + p = ""; + } + Jim_SetResultString(interp, p, -1); + return JIM_OK; +} + +static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + + if (lastSlash) { + Jim_SetResultString(interp, lastSlash + 1, -1); + } + else { + Jim_SetResult(interp, argv[0]); + } + return JIM_OK; +} + +static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_REALPATH + const char *path = Jim_String(argv[0]); + char *newname = Jim_Alloc(MAXPATHLEN + 1); + + if (realpath(path, newname)) { + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1)); + } + else { + Jim_Free(newname); + Jim_SetResult(interp, argv[0]); + } + return JIM_OK; +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif +} + +static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + char *newname = Jim_Alloc(MAXPATHLEN + 1); + char *last = newname; + + *newname = 0; + + /* Simple implementation for now */ + for (i = 0; i < argc; i++) { + int len; + const char *part = Jim_GetString(argv[i], &len); + + if (*part == '/') { + /* Absolute component, so go back to the start */ + last = newname; + } +#if defined(__MINGW32__) + else if (strchr(part, ':')) { + /* Absolute compontent on mingw, so go back to the start */ + last = newname; + } +#endif + else if (part[0] == '.') { + if (part[1] == '/') { + part += 2; + len -= 2; + } + else if (part[1] == 0 && last != newname) { + /* Adding '.' to an existing path does nothing */ + continue; + } + } + + /* Add a slash if needed */ + if (last != newname && last[-1] != '/') { + *last++ = '/'; + } + + if (len) { + if (last + len - newname >= MAXPATHLEN) { + Jim_Free(newname); + Jim_SetResultString(interp, "Path too long", -1); + return JIM_ERR; + } + memcpy(last, part, len); + last += len; + } + + /* Remove a slash if needed */ + if (last > newname + 1 && last[-1] == '/') { + *--last = 0; + } + } + + *last = 0; + + /* Probably need to handle some special cases ... */ + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); + + return JIM_OK; +} + +static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) +{ + const char *path = Jim_String(filename); + int rc = access(path, mode); + + Jim_SetResultBool(interp, rc != -1); + + return JIM_OK; +} + +static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], R_OK); +} + +static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], W_OK); +} + +static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], X_OK); +} + +static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], F_OK); +} + +static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int force = Jim_CompareStringImmediate(interp, argv[0], "-force"); + + if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) { + argc++; + argv--; + } + + while (argc--) { + const char *path = Jim_String(argv[0]); + + if (unlink(path) == -1 && errno != ENOENT) { + if (rmdir(path) == -1) { + /* Maybe try using the script helper */ + if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { + Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + } + } + argv++; + } + return JIM_OK; +} + +#ifdef HAVE_MKDIR_ONE_ARG +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME) +#else +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755) +#endif + +/** + * Create directory, creating all intermediate paths if necessary. + * + * Returns 0 if OK or -1 on failure (and sets errno) + * + * Note: The path may be modified. + */ +static int mkdir_all(char *path) +{ + int ok = 1; + + /* First time just try to make the dir */ + goto first; + + while (ok--) { + /* Must have failed the first time, so recursively make the parent and try again */ + char *slash = strrchr(path, '/'); + + if (slash && slash != path) { + *slash = 0; + if (mkdir_all(path) != 0) { + return -1; + } + *slash = '/'; + } + first: + if (MKDIR_DEFAULT(path) == 0) { + return 0; + } + if (errno == ENOENT) { + /* Create the parent and try again */ + continue; + } + /* Maybe it already exists as a directory */ + if (errno == EEXIST) { + struct stat sb; + + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + return 0; + } + /* Restore errno */ + errno = EEXIST; + } + /* Failed */ + break; + } + return -1; +} + +static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + while (argc--) { + char *path = Jim_StrDup(Jim_String(argv[0])); + int rc = mkdir_all(path); + + Jim_Free(path); + if (rc != 0) { + Jim_SetResultFormatted(interp, "can't create directory \"%#s\": %s", argv[0], + strerror(errno)); + return JIM_ERR; + } + argv++; + } + return JIM_OK; +} + +#ifdef HAVE_MKSTEMP +static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int fd; + char *filename; + const char *template = "/tmp/tcl.tmp.XXXXXX"; + + if (argc >= 1) { + template = Jim_String(argv[0]); + } + filename = Jim_StrDup(template); + + fd = mkstemp(filename); + if (fd < 0) { + Jim_SetResultString(interp, "Failed to create tempfile", -1); + return JIM_ERR; + } + close(fd); + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, filename, -1)); + return JIM_OK; +} +#endif + +static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *source; + const char *dest; + int force = 0; + + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-force")) { + return -1; + } + force++; + argv++; + argc--; + } + + source = Jim_String(argv[0]); + dest = Jim_String(argv[1]); + + if (!force && access(dest, F_OK) == 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": target exists", argv[0], + argv[1]); + return JIM_ERR; + } + + if (rename(source, dest) != 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1], + strerror(errno)); + return JIM_ERR; + } + + return JIM_OK; +} + +static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (stat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +#ifndef HAVE_LSTAT +#define lstat stat +#endif + +static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (lstat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_atime); + return JIM_OK; +} + +static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (argc == 2) { +#ifdef HAVE_UTIMES + jim_wide newtime; + struct timeval times[2]; + + if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) { + return JIM_ERR; + } + + times[1].tv_sec = times[0].tv_sec = newtime; + times[1].tv_usec = times[0].tv_usec = 0; + + if (utimes(Jim_String(argv[0]), times) != 0) { + Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif + } + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_mtime); + return JIM_OK; +} + +static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_EvalPrefix(interp, "file copy", argc, argv); +} + +static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_size); + return JIM_OK; +} + +static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISDIR(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISREG(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +#ifdef HAVE_GETEUID +static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = (geteuid() == sb.st_uid); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} +#endif + +#if defined(HAVE_READLINK) +static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + char *linkValue = Jim_Alloc(MAXPATHLEN + 1); + + int linkLength = readlink(path, linkValue, MAXPATHLEN); + + if (linkLength == -1) { + Jim_Free(linkValue); + Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } + linkValue[linkLength] = 0; + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, linkValue, linkLength)); + return JIM_OK; +} +#endif + +static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); + return JIM_OK; +} + +static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argv[1], &sb); +} + +static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argv[1], &sb); +} + +static const jim_subcmd_type file_command_table[] = { + { .cmd = "atime", + .args = "name", + .function = file_cmd_atime, + .minargs = 1, + .maxargs = 1, + .description = "Last access time" + }, + { .cmd = "mtime", + .args = "name ?time?", + .function = file_cmd_mtime, + .minargs = 1, + .maxargs = 2, + .description = "Get or set last modification time" + }, + { .cmd = "copy", + .args = "?-force? source dest", + .function = file_cmd_copy, + .minargs = 2, + .maxargs = 3, + .description = "Copy source file to destination file" + }, + { .cmd = "dirname", + .args = "name", + .function = file_cmd_dirname, + .minargs = 1, + .maxargs = 1, + .description = "Directory part of the name" + }, + { .cmd = "rootname", + .args = "name", + .function = file_cmd_rootname, + .minargs = 1, + .maxargs = 1, + .description = "Name without any extension" + }, + { .cmd = "extension", + .args = "name", + .function = file_cmd_extension, + .minargs = 1, + .maxargs = 1, + .description = "Last extension including the dot" + }, + { .cmd = "tail", + .args = "name", + .function = file_cmd_tail, + .minargs = 1, + .maxargs = 1, + .description = "Last component of the name" + }, + { .cmd = "normalize", + .args = "name", + .function = file_cmd_normalize, + .minargs = 1, + .maxargs = 1, + .description = "Normalized path of name" + }, + { .cmd = "join", + .args = "name ?name ...?", + .function = file_cmd_join, + .minargs = 1, + .maxargs = -1, + .description = "Join multiple path components" + }, + { .cmd = "readable", + .args = "name", + .function = file_cmd_readable, + .minargs = 1, + .maxargs = 1, + .description = "Is file readable" + }, + { .cmd = "writable", + .args = "name", + .function = file_cmd_writable, + .minargs = 1, + .maxargs = 1, + .description = "Is file writable" + }, + { .cmd = "executable", + .args = "name", + .function = file_cmd_executable, + .minargs = 1, + .maxargs = 1, + .description = "Is file executable" + }, + { .cmd = "exists", + .args = "name", + .function = file_cmd_exists, + .minargs = 1, + .maxargs = 1, + .description = "Does file exist" + }, + { .cmd = "delete", + .args = "?-force|--? name ...", + .function = file_cmd_delete, + .minargs = 1, + .maxargs = -1, + .description = "Deletes the files or directories (must be empty unless -force)" + }, + { .cmd = "mkdir", + .args = "dir ...", + .function = file_cmd_mkdir, + .minargs = 1, + .maxargs = -1, + .description = "Creates the directories" + }, +#ifdef HAVE_MKSTEMP + { .cmd = "tempfile", + .args = "?template?", + .function = file_cmd_tempfile, + .minargs = 0, + .maxargs = 1, + .description = "Creates a temporary filename" + }, +#endif + { .cmd = "rename", + .args = "?-force? source dest", + .function = file_cmd_rename, + .minargs = 2, + .maxargs = 3, + .description = "Renames a file" + }, +#if defined(HAVE_READLINK) + { .cmd = "readlink", + .args = "name", + .function = file_cmd_readlink, + .minargs = 1, + .maxargs = 1, + .description = "Value of the symbolic link" + }, +#endif + { .cmd = "size", + .args = "name", + .function = file_cmd_size, + .minargs = 1, + .maxargs = 1, + .description = "Size of file" + }, + { .cmd = "stat", + .args = "name var", + .function = file_cmd_stat, + .minargs = 2, + .maxargs = 2, + .description = "Stores results of stat in var array" + }, + { .cmd = "lstat", + .args = "name var", + .function = file_cmd_lstat, + .minargs = 2, + .maxargs = 2, + .description = "Stores results of lstat in var array" + }, + { .cmd = "type", + .args = "name", + .function = file_cmd_type, + .minargs = 1, + .maxargs = 1, + .description = "Returns type of the file" + }, +#ifdef HAVE_GETEUID + { .cmd = "owned", + .args = "name", + .function = file_cmd_owned, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if owned by the current owner" + }, +#endif + { .cmd = "isdirectory", + .args = "name", + .function = file_cmd_isdirectory, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if name is a directory" + }, + { .cmd = "isfile", + .args = "name", + .function = file_cmd_isfile, + .minargs = 1, + .maxargs = 1, + .description = "Returns 1 if name is a file" + }, + { + .cmd = 0 + } +}; + +static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "dirname"); + return JIM_ERR; + } + + path = Jim_String(argv[1]); + + if (chdir(path) != 0) { + Jim_SetResultFormatted(interp, "couldn't change working directory to \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const int cwd_len = 2048; + char *cwd = malloc(cwd_len); + + if (getcwd(cwd, cwd_len) == NULL) { + Jim_SetResultString(interp, "Failed to get pwd", -1); + return JIM_ERR; + } +#if defined(__MINGW32__) + { + /* Try to keep backlashes out of paths */ + char *p = cwd; + while ((p = strchr(p, '\\')) != NULL) { + *p++ = '/'; + } + } +#endif + + Jim_SetResultString(interp, cwd, -1); + + free(cwd); + return JIM_OK; +} + +int Jim_fileInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL); + Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); + Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-format.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-format.c new file mode 100755 index 0000000..c9cde89 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-format.c @@ -0,0 +1,433 @@ +/* + * Implements the internals of the format command for jim + * + * The FreeBSD license + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 8.5: + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright (c) 1999 by Scriptics Corporation. + * + * See the file "tcl.license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ +#include <ctype.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "utf8.h" + +#define JIM_UTF_MAX 3 +#define JIM_INTEGER_SPACE 24 +#define MAX_FLOAT_WIDTH 320 + +/** + * Apply the printf-like format in fmtObjPtr with the given arguments. + * + * Returns a new object with zero reference count if OK, or NULL on error. + */ +Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) +{ + const char *span, *format, *formatEnd, *msg; + int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; + static const char * const mixedXPG = + "cannot mix \"%\" and \"%n$\" conversion specifiers"; + static const char * const badIndex[2] = { + "not enough arguments for all format specifiers", + "\"%n$\" argument index out of range" + }; + int formatLen; + Jim_Obj *resultPtr; + + /* A single buffer is used to store numeric fields (with sprintf()) + * This buffer is allocated/reallocated as necessary + */ + char *num_buffer = NULL; + int num_buffer_size = 0; + + span = format = Jim_GetString(fmtObjPtr, &formatLen); + formatEnd = format + formatLen; + resultPtr = Jim_NewStringObj(interp, "", 0); + + while (format != formatEnd) { + char *end; + int gotMinus, sawFlag; + int gotPrecision, useShort; + long width, precision; + int newXpg; + int ch; + int step; + int doubleType; + char pad = ' '; + char spec[2*JIM_INTEGER_SPACE + 12]; + char *p; + + int formatted_chars; + int formatted_bytes; + const char *formatted_buf; + + step = utf8_tounicode(format, &ch); + format += step; + if (ch != '%') { + numBytes += step; + continue; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + numBytes = 0; + } + + /* + * Saw a % : process the format specifier. + * + * Step 0. Handle special case of escaped format marker (i.e., %%). + */ + + step = utf8_tounicode(format, &ch); + if (ch == '%') { + span = format; + numBytes = step; + format += step; + continue; + } + + /* + * Step 1. XPG3 position specifier + */ + + newXpg = 0; + if (isdigit(ch)) { + int position = strtoul(format, &end, 10); + if (*end == '$') { + newXpg = 1; + objIndex = position - 1; + format = end + 1; + step = utf8_tounicode(format, &ch); + } + } + if (newXpg) { + if (gotSequential) { + msg = mixedXPG; + goto errorMsg; + } + gotXpg = 1; + } else { + if (gotXpg) { + msg = mixedXPG; + goto errorMsg; + } + gotSequential = 1; + } + if ((objIndex < 0) || (objIndex >= objc)) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + + /* + * Step 2. Set of flags. Also build up the sprintf spec. + */ + p = spec; + *p++ = '%'; + + gotMinus = 0; + sawFlag = 1; + do { + switch (ch) { + case '-': + gotMinus = 1; + break; + case '0': + pad = ch; + break; + case ' ': + case '+': + case '#': + break; + default: + sawFlag = 0; + continue; + } + *p++ = ch; + format += step; + step = utf8_tounicode(format, &ch); + } while (sawFlag); + + /* + * Step 3. Minimum field width. + */ + + width = 0; + if (isdigit(ch)) { + width = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { + goto error; + } + if (width < 0) { + width = -width; + if (!gotMinus) { + *p++ = '-'; + gotMinus = 1; + } + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + /* + * Step 4. Precision. + */ + + gotPrecision = precision = 0; + if (ch == '.') { + gotPrecision = 1; + format += step; + step = utf8_tounicode(format, &ch); + } + if (isdigit(ch)) { + precision = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { + goto error; + } + + /* + * TODO: Check this truncation logic. + */ + + if (precision < 0) { + precision = 0; + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + /* + * Step 5. Length modifier. + */ + + useShort = 0; + if (ch == 'h') { + useShort = 1; + format += step; + step = utf8_tounicode(format, &ch); + } else if (ch == 'l') { + /* Just for compatibility. All non-short integers are wide. */ + format += step; + step = utf8_tounicode(format, &ch); + if (ch == 'l') { + format += step; + step = utf8_tounicode(format, &ch); + } + } + + format += step; + span = format; + + /* + * Step 6. The actual conversion character. + */ + + if (ch == 'i') { + ch = 'd'; + } + + doubleType = 0; + + /* Each valid conversion will set: + * formatted_buf - the result to be added + * formatted_chars - the length of formatted_buf in characters + * formatted_bytes - the length of formatted_buf in bytes + */ + switch (ch) { + case '\0': + msg = "format string ended in middle of field specifier"; + goto errorMsg; + case 's': { + formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); + formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); + if (gotPrecision && (precision < formatted_chars)) { + /* Need to build a (null terminated) truncated string */ + formatted_chars = precision; + formatted_bytes = utf8_index(formatted_buf, precision); + } + break; + } + case 'c': { + jim_wide code; + + if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { + goto error; + } + /* Just store the value in the 'spec' buffer */ + formatted_bytes = utf8_fromunicode(spec, code); + formatted_buf = spec; + formatted_chars = 1; + break; + } + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + doubleType = 1; + /* fall through */ + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': { + jim_wide w; + double d; + int length; + + /* Fill in the width and precision */ + if (width) { + p += sprintf(p, "%ld", width); + } + if (gotPrecision) { + p += sprintf(p, ".%ld", precision); + } + + /* Now the modifier, and get the actual value here */ + if (doubleType) { + if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { + goto error; + } + length = MAX_FLOAT_WIDTH; + } + else { + if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { + goto error; + } + length = JIM_INTEGER_SPACE; + if (useShort) { + *p++ = 'h'; + if (ch == 'd') { + w = (short)w; + } + else { + w = (unsigned short)w; + } + } + else { + *p++ = 'l'; +#ifdef HAVE_LONG_LONG + if (sizeof(long long) == sizeof(jim_wide)) { + *p++ = 'l'; + } +#endif + } + } + + *p++ = (char) ch; + *p = '\0'; + + /* Adjust length for width and precision */ + if (width > length) { + length = width; + } + if (gotPrecision) { + length += precision; + } + + /* Increase the size of the buffer if needed */ + if (num_buffer_size < length + 1) { + num_buffer_size = length + 1; + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); + } + + if (doubleType) { + snprintf(num_buffer, length + 1, spec, d); + } + else { + formatted_bytes = snprintf(num_buffer, length + 1, spec, w); + } + formatted_chars = formatted_bytes = strlen(num_buffer); + formatted_buf = num_buffer; + break; + } + + default: { + /* Just reuse the 'spec' buffer */ + spec[0] = ch; + spec[1] = '\0'; + Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); + goto error; + } + } + + if (!gotMinus) { + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + } + + Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); + + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + + objIndex += gotSequential; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + } + + Jim_Free(num_buffer); + return resultPtr; + + errorMsg: + Jim_SetResultString(interp, msg, -1); + error: + Jim_FreeNewObj(interp, resultPtr); + Jim_Free(num_buffer); + return NULL; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c new file mode 100755 index 0000000..658e8d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-interactive.c @@ -0,0 +1,137 @@ +#include <errno.h> +#include <string.h> +#include "jim.h" +#include "jimautoconf.h" + +#ifdef USE_LINENOISE +#include <unistd.h> +#include "linenoise.h" +#else + +#define MAX_LINE_LEN 512 + +static char *linenoise(const char *prompt) +{ + char *line = malloc(MAX_LINE_LEN); + + fputs(prompt, stdout); + fflush(stdout); + + if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { + free(line); + return NULL; + } + return line; +} +#endif + +int Jim_InteractivePrompt(Jim_Interp *interp) +{ + int retcode = JIM_OK; + char *history_file = NULL; +#ifdef USE_LINENOISE + const char *home; + + home = getenv("HOME"); + if (home && isatty(STDIN_FILENO)) { + int history_len = strlen(home) + sizeof("/.jim_history"); + history_file = Jim_Alloc(history_len); + snprintf(history_file, history_len, "%s/.jim_history", home); + linenoiseHistoryLoad(history_file); + } +#endif + + printf("Welcome to Jim version %d.%d" JIM_NL, + JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); + + while (1) { + Jim_Obj *scriptObjPtr; + const char *result; + int reslen; + char prompt[20]; + const char *str; + + if (retcode != 0) { + const char *retcodestr = Jim_ReturnCode(retcode); + + if (*retcodestr == '?') { + snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode); + } + else { + snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr); + } + } + else { + prompt[0] = '\0'; + } + strcat(prompt, ". "); + + scriptObjPtr = Jim_NewStringObj(interp, "", 0); + Jim_IncrRefCount(scriptObjPtr); + while (1) { + char state; + int len; + char *line; + + line = linenoise(prompt); + if (line == NULL) { + if (errno == EINTR) { + continue; + } + Jim_DecrRefCount(interp, scriptObjPtr); + goto out; + } + if (Jim_Length(scriptObjPtr) != 0) { + Jim_AppendString(interp, scriptObjPtr, "\n", 1); + } + Jim_AppendString(interp, scriptObjPtr, line, -1); + free(line); + str = Jim_GetString(scriptObjPtr, &len); + if (len == 0) { + continue; + } + if (Jim_ScriptIsComplete(str, len, &state)) + break; + + snprintf(prompt, sizeof(prompt), "%c> ", state); + } +#ifdef USE_LINENOISE + if (strcmp(str, "h") == 0) { + /* built-in history command */ + int i; + int len; + char **history = linenoiseHistory(&len); + for (i = 0; i < len; i++) { + printf("%4d %s\n", i + 1, history[i]); + } + Jim_DecrRefCount(interp, scriptObjPtr); + continue; + } + + linenoiseHistoryAdd(Jim_String(scriptObjPtr)); + if (history_file) { + linenoiseHistorySave(history_file); + } +#endif + retcode = Jim_EvalObj(interp, scriptObjPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + + + + if (retcode == JIM_EXIT) { + Jim_Free(history_file); + return JIM_EXIT; + } + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + } + result = Jim_GetString(Jim_GetResult(interp), &reslen); + if (reslen) { + printf("%s\n", result); + } + } + out: + Jim_Free(history_file); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-load.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-load.c new file mode 100755 index 0000000..4dc6ed2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-load.c @@ -0,0 +1,126 @@ +#include "jim.h" +#include "jimautoconf.h" +#include <string.h> + +/* ----------------------------------------------------------------------------- + * Dynamic libraries support (WIN32 not supported) + * ---------------------------------------------------------------------------*/ + +#if defined(HAVE_DLOPEN) || defined(HAVE_DLOPEN_COMPAT) + +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifndef RTLD_NOW + #define RTLD_NOW 0 +#endif +#ifndef RTLD_LOCAL + #define RTLD_LOCAL 0 +#endif + +/** + * Note that Jim_LoadLibrary() requires a path to an existing file. + * + * If it is necessary to search JIM_LIBPATH, use Jim_PackageRequire() instead. + */ +int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) +{ + void *handle = dlopen(pathName, RTLD_NOW | RTLD_LOCAL); + if (handle == NULL) { + Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName, + dlerror()); + } + else { + /* We use a unique init symbol depending on the extension name. + * This is done for compatibility between static and dynamic extensions. + * For extension readline.so, the init symbol is "Jim_readlineInit" + */ + const char *pt; + const char *pkgname; + int pkgnamelen; + char initsym[40]; + int (*onload) (Jim_Interp *); + + pt = strrchr(pathName, '/'); + if (pt) { + pkgname = pt + 1; + } + else { + pkgname = pathName; + } + pt = strchr(pkgname, '.'); + if (pt) { + pkgnamelen = pt - pkgname; + } + else { + pkgnamelen = strlen(pkgname); + } + snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname); + + if ((onload = dlsym(handle, initsym)) == NULL) { + Jim_SetResultFormatted(interp, + "No %s symbol found in extension %s", initsym, pathName); + } + else if (onload(interp) != JIM_ERR) { + /* Add this handle to the stack of handles to be freed */ + if (!interp->loadHandles) { + interp->loadHandles = Jim_Alloc(sizeof(*interp->loadHandles)); + Jim_InitStack(interp->loadHandles); + } + Jim_StackPush(interp->loadHandles, handle); + + Jim_SetEmptyResult(interp); + + return JIM_OK; + } + } + if (handle) { + dlclose(handle); + } + return JIM_ERR; +} + +static void JimFreeOneLoadHandle(void *handle) +{ + dlclose(handle); +} + +void Jim_FreeLoadHandles(Jim_Interp *interp) +{ + if (interp->loadHandles) { + Jim_FreeStackElements(interp->loadHandles, JimFreeOneLoadHandle); + Jim_Free(interp->loadHandles); + } +} + +#else /* JIM_DYNLIB */ +int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(pathName); + + Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1); + return JIM_ERR; +} + +void Jim_FreeLoadHandles(Jim_Interp *interp) +{ +} +#endif /* JIM_DYNLIB */ + +/* [load] */ +static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "libaryFile"); + return JIM_ERR; + } + return Jim_LoadLibrary(interp, Jim_String(argv[1])); +} + +int Jim_loadInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c new file mode 100755 index 0000000..be94f15 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.c @@ -0,0 +1,338 @@ +#include <string.h> +#include <jim-nvp.h> + +int Jim_GetNvp(Jim_Interp *interp, + Jim_Obj *objPtr, const Jim_Nvp * nvp_table, const Jim_Nvp ** result) +{ + Jim_Nvp *n; + int e; + + e = Jim_Nvp_name2value_obj(interp, nvp_table, objPtr, &n); + if (e == JIM_ERR) { + return e; + } + + /* Success? found? */ + if (n->name) { + /* remove const */ + *result = (Jim_Nvp *) n; + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp * p, const char *name) +{ + while (p->name) { + if (0 == strcmp(name, p->name)) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + +Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp * p, const char *name) +{ + while (p->name) { + if (0 == strcasecmp(name, p->name)) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + +int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result) +{ + return Jim_Nvp_name2value(interp, p, Jim_String(o), result); +} + + +int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp * _p, const char *name, Jim_Nvp ** result) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_name2value_simple(_p, name); + + /* result */ + if (result) { + *result = (Jim_Nvp *) (p); + } + + /* found? */ + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +int +Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** puthere) +{ + return Jim_Nvp_name2value_nocase(interp, p, Jim_String(o), puthere); +} + +int +Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp * _p, const char *name, + Jim_Nvp ** puthere) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_name2value_nocase_simple(_p, name); + + if (puthere) { + *puthere = (Jim_Nvp *) (p); + } + /* found */ + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + + +int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp * p, Jim_Obj *o, Jim_Nvp ** result) +{ + int e;; + jim_wide w; + + e = Jim_GetWide(interp, o, &w); + if (e != JIM_OK) { + return e; + } + + return Jim_Nvp_value2name(interp, p, w, result); +} + +Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp * p, int value) +{ + while (p->name) { + if (value == p->value) { + break; + } + p++; + } + return ((Jim_Nvp *) (p)); +} + + +int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp * _p, int value, Jim_Nvp ** result) +{ + const Jim_Nvp *p; + + p = Jim_Nvp_value2name_simple(_p, value); + + if (result) { + *result = (Jim_Nvp *) (p); + } + + if (p->name) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + + +int Jim_GetOpt_Setup(Jim_GetOptInfo * p, Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + memset(p, 0, sizeof(*p)); + p->interp = interp; + p->argc = argc; + p->argv = argv; + + return JIM_OK; +} + +void Jim_GetOpt_Debug(Jim_GetOptInfo * p) +{ + int x; + + fprintf(stderr, "---args---\n"); + for (x = 0; x < p->argc; x++) { + fprintf(stderr, "%2d) %s\n", x, Jim_String(p->argv[x])); + } + fprintf(stderr, "-------\n"); +} + + +int Jim_GetOpt_Obj(Jim_GetOptInfo * goi, Jim_Obj **puthere) +{ + Jim_Obj *o; + + o = NULL; // failure + if (goi->argc) { + // success + o = goi->argv[0]; + goi->argc -= 1; + goi->argv += 1; + } + if (puthere) { + *puthere = o; + } + if (o != NULL) { + return JIM_OK; + } + else { + return JIM_ERR; + } +} + +int Jim_GetOpt_String(Jim_GetOptInfo * goi, char **puthere, int *len) +{ + int r; + Jim_Obj *o; + const char *cp; + + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + cp = Jim_GetString(o, len); + if (puthere) { + /* remove const */ + *puthere = (char *)(cp); + } + } + return r; +} + +int Jim_GetOpt_Double(Jim_GetOptInfo * goi, double *puthere) +{ + int r; + Jim_Obj *o; + double _safe; + + if (puthere == NULL) { + puthere = &_safe; + } + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + r = Jim_GetDouble(goi->interp, o, puthere); + if (r != JIM_OK) { + Jim_SetResultFormatted(goi->interp, "not a number: %#s", o); + } + } + return r; +} + +int Jim_GetOpt_Wide(Jim_GetOptInfo * goi, jim_wide * puthere) +{ + int r; + Jim_Obj *o; + jim_wide _safe; + + if (puthere == NULL) { + puthere = &_safe; + } + + r = Jim_GetOpt_Obj(goi, &o); + if (r == JIM_OK) { + r = Jim_GetWide(goi->interp, o, puthere); + } + return r; +} + +int Jim_GetOpt_Nvp(Jim_GetOptInfo * goi, const Jim_Nvp * nvp, Jim_Nvp ** puthere) +{ + Jim_Nvp *_safe; + Jim_Obj *o; + int e; + + if (puthere == NULL) { + puthere = &_safe; + } + + e = Jim_GetOpt_Obj(goi, &o); + if (e == JIM_OK) { + e = Jim_Nvp_name2value_obj(goi->interp, nvp, o, puthere); + } + + return e; +} + +void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo * goi, const Jim_Nvp * nvptable, int hadprefix) +{ + if (hadprefix) { + Jim_SetResult_NvpUnknown(goi->interp, goi->argv[-2], goi->argv[-1], nvptable); + } + else { + Jim_SetResult_NvpUnknown(goi->interp, NULL, goi->argv[-1], nvptable); + } +} + + +int Jim_GetOpt_Enum(Jim_GetOptInfo * goi, const char *const *lookup, int *puthere) +{ + int _safe; + Jim_Obj *o; + int e; + + if (puthere == NULL) { + puthere = &_safe; + } + e = Jim_GetOpt_Obj(goi, &o); + if (e == JIM_OK) { + e = Jim_GetEnum(goi->interp, o, lookup, puthere, "option", JIM_ERRMSG); + } + return e; +} + +void +Jim_SetResult_NvpUnknown(Jim_Interp *interp, + Jim_Obj *param_name, Jim_Obj *param_value, const Jim_Nvp * nvp) +{ + if (param_name) { + Jim_SetResultFormatted(interp, "%#s: Unknown: %#s, try one of: ", param_name, param_value); + } + else { + Jim_SetResultFormatted(interp, "Unknown param: %#s, try one of: ", param_value); + } + while (nvp->name) { + const char *a; + const char *b; + + if ((nvp + 1)->name) { + a = nvp->name; + b = ", "; + } + else { + a = "or "; + b = nvp->name; + } + Jim_AppendStrings(interp, Jim_GetResult(interp), a, b, NULL); + nvp++; + } +} + +const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static Jim_Obj *debug_string_obj; + + int x; + + if (debug_string_obj) { + Jim_FreeObj(interp, debug_string_obj); + } + + debug_string_obj = Jim_NewEmptyStringObj(interp); + for (x = 0; x < argc; x++) { + Jim_AppendStrings(interp, debug_string_obj, Jim_String(argv[x]), " ", NULL); + } + + return Jim_String(debug_string_obj); +} + +int Jim_nvpInit(Jim_Interp *interp) +{ + /* This is really a helper library, not an extension, but this is the easy way */ + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h new file mode 100755 index 0000000..12ff889 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-nvp.h @@ -0,0 +1,275 @@ +#ifndef JIM_NVP_H +#define JIM_NVP_H + +#include <jim.h> + +/** Name Value Pairs, aka: NVP + * - Given a string - return the associated int. + * - Given a number - return the associated string. + * . + * + * Very useful when the number is not a simple index into an array of + * known string, or there may be multiple strings (aliases) that mean then same + * thing. + * + * An NVP Table is terminated with ".name = NULL". + * + * During the 'name2value' operation, if no matching string is found + * the pointer to the terminal element (with p->name == NULL) is returned. + * + * Example: + * \code + * const Jim_Nvp yn[] = { + * { "yes", 1 }, + * { "no" , 0 }, + * { "yep", 1 }, + * { "nope", 0 }, + * { NULL, -1 }, + * }; + * + * Jim_Nvp *result + * e = Jim_Nvp_name2value(interp, yn, "y", &result); + * returns &yn[0]; + * e = Jim_Nvp_name2value(interp, yn, "n", &result); + * returns &yn[1]; + * e = Jim_Nvp_name2value(interp, yn, "Blah", &result); + * returns &yn[4]; + * \endcode + * + * During the number2name operation, the first matching value is returned. + */ +typedef struct { + const char *name; + int value; +} Jim_Nvp; + + +int Jim_GetNvp (Jim_Interp *interp, + Jim_Obj *objPtr, + const Jim_Nvp *nvp_table, + const Jim_Nvp **result); + +/* Name Value Pairs Operations */ +Jim_Nvp *Jim_Nvp_name2value_simple(const Jim_Nvp *nvp_table, const char *name); +Jim_Nvp *Jim_Nvp_name2value_nocase_simple(const Jim_Nvp *nvp_table, const char *name); +Jim_Nvp *Jim_Nvp_value2name_simple(const Jim_Nvp *nvp_table, int v); + +int Jim_Nvp_name2value(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); +int Jim_Nvp_name2value_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, const char *name, Jim_Nvp **result); +int Jim_Nvp_value2name(Jim_Interp *interp, const Jim_Nvp *nvp_table, int value, Jim_Nvp **result); + +int Jim_Nvp_name2value_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); +int Jim_Nvp_name2value_obj_nocase(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *name_obj, Jim_Nvp **result); +int Jim_Nvp_value2name_obj(Jim_Interp *interp, const Jim_Nvp *nvp_table, Jim_Obj *value_obj, Jim_Nvp **result); + +/** prints a nice 'unknown' parameter error message to the 'result' */ +void Jim_SetResult_NvpUnknown(Jim_Interp *interp, + Jim_Obj *param_name, + Jim_Obj *param_value, + const Jim_Nvp *nvp_table); + + +/** Debug: convert argc/argv into a printable string for printf() debug + * + * \param interp - the interpeter + * \param argc - arg count + * \param argv - the objects + * + * \returns string pointer holding the text. + * + * Note, next call to this function will free the old (last) string. + * + * For example might want do this: + * \code + * fp = fopen("some.file.log", "a"); + * fprintf(fp, "PARAMS are: %s\n", Jim_DebugArgvString(interp, argc, argv)); + * fclose(fp); + * \endcode + */ +const char *Jim_Debug_ArgvString(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + + +/** A TCL -ish GetOpt like code. + * + * Some TCL objects have various "configuration" values. + * For example - in Tcl/Tk the "buttons" have many options. + * + * Usefull when dealing with command options. + * that may come in any order... + * + * Does not support "-foo = 123" type options. + * Only supports tcl type options, like "-foo 123" + */ + +typedef struct jim_getopt { + Jim_Interp *interp; + int argc; + Jim_Obj * const * argv; + int isconfigure; /* non-zero if configure */ +} Jim_GetOptInfo; + +/** GetOpt - how to. + * + * Example (short and incomplete): + * \code + * Jim_GetOptInfo goi; + * + * Jim_GetOpt_Setup(&goi, interp, argc, argv); + * + * while (goi.argc) { + * e = Jim_GetOpt_Nvp(&goi, nvp_options, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&goi, nvp_options, 0); + * return e; + * } + * + * switch (n->value) { + * case ALIVE: + * printf("Option ALIVE specified\n"); + * break; + * case FIRST: + * if (goi.argc < 1) { + * .. not enough args error .. + * } + * Jim_GetOpt_String(&goi, &cp, NULL); + * printf("FIRSTNAME: %s\n", cp); + * case AGE: + * Jim_GetOpt_Wide(&goi, &w); + * printf("AGE: %d\n", (int)(w)); + * break; + * case POLITICS: + * e = Jim_GetOpt_Nvp(&goi, nvp_politics, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&goi, nvp_politics, 1); + * return e; + * } + * } + * } + * + * \endcode + * + */ + +/** Setup GETOPT + * + * \param goi - get opt info to be initialized + * \param interp - jim interp + * \param argc - argc count. + * \param argv - argv (will be copied) + * + * \code + * Jim_GetOptInfo goi; + * + * Jim_GetOptSetup(&goi, interp, argc, argv); + * \endcode + */ + +int Jim_GetOpt_Setup(Jim_GetOptInfo *goi, + Jim_Interp *interp, + int argc, + Jim_Obj * const * argv); + + +/** Debug - Dump parameters to stderr + * \param goi - current parameters + */ +void Jim_GetOpt_Debug(Jim_GetOptInfo *goi); + + + +/** Remove argv[0] from the list. + * + * \param goi - get opt info + * \param puthere - where param is put + * + */ +int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere); + +/** Remove argv[0] as string. + * + * \param goi - get opt info + * \param puthere - where param is put + * \param len - return its length + */ +int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len); + +/** Remove argv[0] as double. + * + * \param goi - get opt info + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Double(Jim_GetOptInfo *goi, double *puthere); + +/** Remove argv[0] as wide. + * + * \param goi - get opt info + * \param puthere - where param is put. + */ +int Jim_GetOpt_Wide(Jim_GetOptInfo *goi, jim_wide *puthere); + +/** Remove argv[0] as NVP. + * + * \param goi - get opt info + * \param lookup - nvp lookup table + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Nvp(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, Jim_Nvp **puthere); + +/** Create an appropriate error message for an NVP. + * + * \param goi - options info + * \param lookup - the NVP table that was used. + * \param hadprefix - 0 or 1 if the option had a prefix. + * + * This function will set the "interp->result" to a human readable + * error message listing the available options. + * + * This function assumes the previous option argv[-1] is the unknown string. + * + * If this option had some prefix, then pass "hadprefix = 1" else pass "hadprefix = 0" + * + * Example: + * \code + * + * while (goi.argc) { + * // Get the next option + * e = Jim_GetOpt_Nvp(&goi, cmd_options, &n); + * if (e != JIM_OK) { + * // option was not recognized + * // pass 'hadprefix = 0' because there is no prefix + * Jim_GetOpt_NvpUnknown(&goi, cmd_options, 0); + * return e; + * } + * + * switch (n->value) { + * case OPT_SEX: + * // handle: --sex male | female | lots | needmore + * e = Jim_GetOpt_Nvp(&goi, &nvp_sex, &n); + * if (e != JIM_OK) { + * Jim_GetOpt_NvpUnknown(&ogi, nvp_sex, 1); + * return e; + * } + * printf("Code: (%d) is %s\n", n->value, n->name); + * break; + * case ...: + * [snip] + * } + * } + * \endcode + * + */ +void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadprefix); + + +/** Remove argv[0] as Enum + * + * \param goi - get opt info + * \param lookup - lookup table. + * \param puthere - where param is put. + * + */ +int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char * const * lookup, int *puthere); + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-pack.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-pack.c new file mode 100755 index 0000000..88bf2c1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-pack.c @@ -0,0 +1,380 @@ +#include <string.h> +#include <jim.h> + +/* Provides the [pack] and [unpack] commands to pack and unpack + * a binary string to/from arbitrary width integers and strings. + * + * This may be used to implement the [binary] command. + */ + +/** + * Big endian bit test. + * + * Considers 'bitvect' as a big endian bit stream and returns + * bit 'b' as zero or non-zero. + */ +static int JimTestBitBigEndian(const unsigned char *bitvec, int b) +{ + div_t pos = div(b, 8); + return bitvec[pos.quot] & (1 << (7 - pos.rem)); +} + +/** + * Little endian bit test. + * + * Considers 'bitvect' as a little endian bit stream and returns + * bit 'b' as zero or non-zero. + */ +static int JimTestBitLittleEndian(const unsigned char *bitvec, int b) +{ + div_t pos = div(b, 8); + return bitvec[pos.quot] & (1 << pos.rem); +} + +/** + * Sign extends the given value, 'n' of width 'width' bits. + * + * For example, sign extending 0x80 with a width of 8, produces -128 + */ +static jim_wide JimSignExtend(jim_wide n, int width) +{ + if (width == sizeof(jim_wide) * 8) { + /* Can't sign extend the maximum size integer */ + return n; + } + if (n & ((jim_wide)1 << (width - 1))) { + /* Need to extend */ + n -= ((jim_wide)1 << width); + } + + return n; +} + +/** + * Big endian integer extraction. + * + * Considers 'bitvect' as a big endian bit stream. + * Returns an integer of the given width (in bits) + * starting at the given position (in bits). + * + * The pos/width must represent bits inside bitvec, + * and the width be no more than the width of jim_wide. + */ +static jim_wide JimBitIntBigEndian(const unsigned char *bitvec, int pos, int width) +{ + jim_wide result = 0; + int i; + + /* Aligned, byte extraction */ + if (pos % 8 == 0 && width % 8 == 0) { + for (i = 0; i < width; i += 8) { + result = (result << 8) + bitvec[(pos + i) / 8]; + } + return result; + } + + /* Unaligned */ + for (i = 0; i < width; i++) { + if (JimTestBitBigEndian(bitvec, pos + width - i - 1)) { + result |= ((jim_wide)1 << i); + } + } + + return result; +} + +/** + * Little endian integer extraction. + * + * Like JimBitIntBigEndian() but considers 'bitvect' as a little endian bit stream. + */ +static jim_wide JimBitIntLittleEndian(const unsigned char *bitvec, int pos, int width) +{ + jim_wide result = 0; + int i; + + /* Aligned, byte extraction */ + if (pos % 8 == 0 && width % 8 == 0) { + for (i = 0; i < width; i += 8) { + result += (jim_wide)bitvec[(pos + i) / 8] << i; + } + return result; + } + + /* Unaligned */ + for (i = 0; i < width; i++) { + if (JimTestBitLittleEndian(bitvec, pos + i)) { + result |= ((jim_wide)1 << i); + } + } + + return result; +} + +/** + * Big endian bit set. + * + * Considers 'bitvect' as a big endian bit stream and sets + * bit 'b' to 'bit' + */ +static void JimSetBitBigEndian(unsigned char *bitvec, int b, int bit) +{ + div_t pos = div(b, 8); + if (bit) { + bitvec[pos.quot] |= (1 << (7 - pos.rem)); + } + else { + bitvec[pos.quot] &= ~(1 << (7 - pos.rem)); + } +} + +/** + * Little endian bit set. + * + * Considers 'bitvect' as a little endian bit stream and sets + * bit 'b' to 'bit' + */ +static void JimSetBitLittleEndian(unsigned char *bitvec, int b, int bit) +{ + div_t pos = div(b, 8); + if (bit) { + bitvec[pos.quot] |= (1 << pos.rem); + } + else { + bitvec[pos.quot] &= ~(1 << pos.rem); + } +} + +/** + * Big endian integer packing. + * + * Considers 'bitvect' as a big endian bit stream. + * Packs integer 'value' of the given width (in bits) + * starting at the given position (in bits). + * + * The pos/width must represent bits inside bitvec, + * and the width be no more than the width of jim_wide. + */ +static void JimSetBitsIntBigEndian(unsigned char *bitvec, jim_wide value, int pos, int width) +{ + int i; + + /* Common fast option */ + if (pos % 8 == 0 && width == 8) { + bitvec[pos / 8] = value; + return; + } + + for (i = 0; i < width; i++) { + int bit = !!(value & ((jim_wide)1 << i)); + JimSetBitBigEndian(bitvec, pos + width - i - 1, bit); + } +} + +/** + * Little endian version of JimSetBitsIntBigEndian() + */ +static void JimSetBitsIntLittleEndian(unsigned char *bitvec, jim_wide value, int pos, int width) +{ + int i; + + /* Common fast option */ + if (pos % 8 == 0 && width == 8) { + bitvec[pos / 8] = value; + return; + } + + for (i = 0; i < width; i++) { + int bit = !!(value & ((jim_wide)1 << i)); + JimSetBitLittleEndian(bitvec, pos + i, bit); + } +} + +/** + * [unpack] + * + * Usage: unpack binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth + * + * Unpacks bits from $binvalue at bit position $bitpos and with $bitwidth. + * Interprets the value according to the type and returns it. + */ +static int Jim_UnpackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int option; + static const char * const options[] = { "-intbe", "-intle", "-uintbe", "-uintle", "-str", NULL }; + enum { OPT_INTBE, OPT_INTLE, OPT_UINTBE, OPT_UINTLE, OPT_STR, }; + jim_wide pos; + jim_wide width; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "binvalue -intbe|-intle|-uintbe|-uintle|-str bitpos bitwidth"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + if (Jim_GetWide(interp, argv[3], &pos) != JIM_OK) { + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) { + return JIM_ERR; + } + + if (option == OPT_STR) { + int len; + const char *str = Jim_GetString(argv[1], &len); + + if (width % 8 || pos % 8) { + Jim_SetResultString(interp, "string field is not on a byte boundary", -1); + return JIM_ERR; + } + + if (pos >= 0 && width > 0 && pos < len * 8) { + if (pos + width > len * 8) { + width = len * 8 - pos; + } + Jim_SetResultString(interp, str + pos / 8, width / 8); + } + return JIM_OK; + } + else { + int len; + const unsigned char *str = (const unsigned char *)Jim_GetString(argv[1], &len); + jim_wide result = 0; + + if (width > sizeof(jim_wide) * 8) { + Jim_SetResultFormatted(interp, "int field is too wide: %#s", argv[4]); + return JIM_ERR; + } + + if (pos >= 0 && width > 0 && pos < len * 8) { + if (pos + width > len * 8) { + width = len * 8 - pos; + } + if (option == OPT_INTBE || option == OPT_UINTBE) { + result = JimBitIntBigEndian(str, pos, width); + } + else { + result = JimBitIntLittleEndian(str, pos, width); + } + if (option == OPT_INTBE || option == OPT_INTLE) { + result = JimSignExtend(result, width); + } + } + Jim_SetResultInt(interp, result); + return JIM_OK; + } +} + +/** + * [pack] + * + * Usage: pack varname value -intle|-intbe|-str width ?bitoffset? + * + * Packs the binary representation of 'value' into the variable of the given name. + * The value is packed according to the given type, width and bitoffset. + * The variable is created if necessary (like [append]) + * Ihe variable is expanded if necessary + */ +static int Jim_PackCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int option; + static const char * const options[] = { "-intle", "-intbe", "-str", NULL }; + enum { OPT_LE, OPT_BE, OPT_STR }; + jim_wide pos = 0; + jim_wide width; + jim_wide value; + Jim_Obj *stringObjPtr; + int len; + int freeobj = 0; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 1, argv, "varName value -intle|-intbe|-str bitwidth ?bitoffset?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[3], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + if (option != OPT_STR && Jim_GetWide(interp, argv[2], &value) != JIM_OK) { + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[4], &width) != JIM_OK) { + return JIM_ERR; + } + if (width <= 0 || (option == OPT_STR && width % 8) || (option != OPT_STR && width > sizeof(jim_wide) * 8)) { + Jim_SetResultFormatted(interp, "bad bitwidth: %#s", argv[5]); + return JIM_ERR; + } + if (argc == 6) { + if (Jim_GetWide(interp, argv[5], &pos) != JIM_OK) { + return JIM_ERR; + } + if (pos < 0 || (option == OPT_STR && pos % 8)) { + Jim_SetResultFormatted(interp, "bad bitoffset: %#s", argv[5]); + return JIM_ERR; + } + } + + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!stringObjPtr) { + /* Create the string if it doesn't exist */ + stringObjPtr = Jim_NewEmptyStringObj(interp); + freeobj = 1; + } + else if (Jim_IsShared(stringObjPtr)) { + freeobj = 1; + stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); + } + + len = Jim_Length(stringObjPtr) * 8; + + /* Extend the string as necessary first */ + while (len < pos + width) { + Jim_AppendString(interp, stringObjPtr, "", 1); + len += 8; + } + + Jim_SetResultInt(interp, pos + width); + + /* Now set the bits. Note that the the string *must* have no non-string rep + * since we are writing the bytes directly. + */ + Jim_AppendString(interp, stringObjPtr, "", 0); + + if (option == OPT_BE) { + JimSetBitsIntBigEndian((unsigned char *)stringObjPtr->bytes, value, pos, width); + } + else if (option == OPT_LE) { + JimSetBitsIntLittleEndian((unsigned char *)stringObjPtr->bytes, value, pos, width); + } + else { + pos /= 8; + width /= 8; + + if (width > Jim_Length(argv[2])) { + width = Jim_Length(argv[2]); + } + memcpy(stringObjPtr->bytes + pos, Jim_GetString(argv[2], NULL), width); + /* No padding is needed since the string is already extended */ + } + + if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { + if (freeobj) { + Jim_FreeNewObj(interp, stringObjPtr); + return JIM_ERR; + } + } + return JIM_OK; +} + +int Jim_packInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "pack", "1.0", JIM_ERRMSG)) { + return JIM_ERR; + } + + Jim_CreateCommand(interp, "unpack", Jim_UnpackCmd, NULL, NULL); + Jim_CreateCommand(interp, "pack", Jim_PackCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-package.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-package.c new file mode 100755 index 0000000..9caec0d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-package.c @@ -0,0 +1,259 @@ +#include <unistd.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" + +/* ----------------------------------------------------------------------------- + * Packages handling + * ---------------------------------------------------------------------------*/ + +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) +{ + /* If the package was already provided returns an error. */ + Jim_HashEntry *he = Jim_FindHashEntry(&interp->packages, name); + + /* An empty result means the automatic entry. This can be replaced */ + if (he && *(const char *)he->u.val) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "package \"%s\" was already provided", name); + } + return JIM_ERR; + } + if (he) { + Jim_DeleteHashEntry(&interp->packages, name); + } + Jim_AddHashEntry(&interp->packages, name, (char *)ver); + return JIM_OK; +} + +static char *JimFindPackage(Jim_Interp *interp, char **prefixes, int prefixc, const char *pkgName) +{ + int i; + char *buf = Jim_Alloc(JIM_PATH_LEN); + + for (i = 0; i < prefixc; i++) { + if (prefixes[i] == NULL) + continue; + + /* Loadable modules are tried first */ +#ifdef jim_ext_load + snprintf(buf, JIM_PATH_LEN, "%s/%s.so", prefixes[i], pkgName); + if (access(buf, R_OK) == 0) { + return buf; + } +#endif + if (strcmp(prefixes[i], ".") == 0) { + snprintf(buf, JIM_PATH_LEN, "%s.tcl", pkgName); + } + else { + snprintf(buf, JIM_PATH_LEN, "%s/%s.tcl", prefixes[i], pkgName); + } + + if (access(buf, R_OK) == 0) { + return buf; + } + } + Jim_Free(buf); + return NULL; +} + +/* Search for a suitable package under every dir specified by JIM_LIBPATH, + * and load it if possible. If a suitable package was loaded with success + * JIM_OK is returned, otherwise JIM_ERR is returned. */ +static int JimLoadPackage(Jim_Interp *interp, const char *name, int flags) +{ + Jim_Obj *libPathObjPtr; + char **prefixes, *path; + int prefixc, i, retCode = JIM_ERR; + + libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE); + if (libPathObjPtr == NULL) { + prefixc = 0; + libPathObjPtr = NULL; + } + else { + Jim_IncrRefCount(libPathObjPtr); + prefixc = Jim_ListLength(interp, libPathObjPtr); + } + + prefixes = Jim_Alloc(sizeof(char *) * prefixc); + for (i = 0; i < prefixc; i++) { + Jim_Obj *prefixObjPtr; + + if (Jim_ListIndex(interp, libPathObjPtr, i, &prefixObjPtr, JIM_NONE) != JIM_OK) { + prefixes[i] = NULL; + continue; + } + prefixes[i] = Jim_StrDup(Jim_String(prefixObjPtr)); + } + + /* Scan every directory for the the first match */ + path = JimFindPackage(interp, prefixes, prefixc, name); + if (path != NULL) { + char *p = strrchr(path, '.'); + + /* Note: Even if the file fails to load, we consider the package loaded. + * This prevents issues with recursion. + * Use a dummy version of "" to signify this case. + */ + Jim_PackageProvide(interp, name, "", 0); + + /* Try to load/source it */ + if (p && strcmp(p, ".tcl") == 0) { + retCode = Jim_EvalFileGlobal(interp, path); + } +#ifdef jim_ext_load + else { + retCode = Jim_LoadLibrary(interp, path); + } +#endif + if (retCode != JIM_OK) { + /* Upon failure, remove the dummy entry */ + Jim_DeleteHashEntry(&interp->packages, name); + } + Jim_Free(path); + } + for (i = 0; i < prefixc; i++) + Jim_Free(prefixes[i]); + Jim_Free(prefixes); + if (libPathObjPtr) + Jim_DecrRefCount(interp, libPathObjPtr); + return retCode; +} + +int Jim_PackageRequire(Jim_Interp *interp, const char *name, int flags) +{ + Jim_HashEntry *he; + + /* Start with an empty error string */ + Jim_SetResultString(interp, "", 0); + + he = Jim_FindHashEntry(&interp->packages, name); + if (he == NULL) { + /* Try to load the package. */ + int retcode = JimLoadPackage(interp, name, flags); + if (retcode != JIM_OK) { + if (flags & JIM_ERRMSG) { + int len; + + Jim_GetString(Jim_GetResult(interp), &len); + Jim_SetResultFormatted(interp, "%#s%sCan't load package %s", + Jim_GetResult(interp), len ? "\n" : "", name); + } + return retcode; + } + + /* In case the package did no 'package provide' */ + Jim_PackageProvide(interp, name, "1.0", 0); + + /* Now it must exist */ + he = Jim_FindHashEntry(&interp->packages, name); + } + + Jim_SetResultString(interp, he->u.val, -1); + return JIM_OK; +} + +/* + *---------------------------------------------------------------------- + * + * package provide name ?version? + * + * This procedure is invoked to declare that a particular version + * of a particular package is now present in an interpreter. There + * must not be any other version of this package already + * provided in the interpreter. + * + * Results: + * Returns JIM_OK and sets the package version (or 1.0 if not specified). + * + *---------------------------------------------------------------------- + */ +static int package_cmd_provide(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *version = "1.0"; + + if (argc == 2) { + version = Jim_String(argv[1]); + } + return Jim_PackageProvide(interp, Jim_String(argv[0]), version, JIM_ERRMSG); +} + +/* + *---------------------------------------------------------------------- + * + * package require name ?version? + * + * This procedure is load a given package. + * Note that the version is ignored. + * + * Results: + * Returns JIM_OK and sets the package version. + * + *---------------------------------------------------------------------- + */ +static int package_cmd_require(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* package require failing is important enough to add to the stack */ + interp->addStackTrace++; + + return Jim_PackageRequire(interp, Jim_String(argv[0]), JIM_ERRMSG); +} + +/* + *---------------------------------------------------------------------- + * + * package list + * + * Returns a list of known packages + * + * Results: + * Returns JIM_OK and sets a list of known packages. + * + *---------------------------------------------------------------------- + */ +static int package_cmd_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + htiter = Jim_GetHashTableIterator(&interp->packages); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); + } + Jim_FreeHashTableIterator(htiter); + + Jim_SetResult(interp, listObjPtr); + + return JIM_OK; +} + +static const jim_subcmd_type package_command_table[] = { + {.cmd = "provide", + .args = "name ?version?", + .function = package_cmd_provide, + .minargs = 1, + .maxargs = 2, + .description = "Indicates that the current script provides the given package"}, + {.cmd = "require", + .args = "name ?version?", + .function = package_cmd_require, + .minargs = 1, + .maxargs = 2, + .description = "Loads the given package by looking in standard places"}, + {.cmd = "list", + .function = package_cmd_list, + .minargs = 0, + .maxargs = 0, + .description = "Lists all known packages"}, + {0} +}; + +int Jim_packageInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "package", Jim_SubCmdProc, (void *)package_command_table, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-posix.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-posix.c new file mode 100755 index 0000000..0cf3604 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-posix.c @@ -0,0 +1,231 @@ + +/* Jim - POSIX extension + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <unistd.h> +#include <string.h> +#include <signal.h> +#include <errno.h> + +#include "jim.h" +#include "jimautoconf.h" + +#ifdef HAVE_SYS_SYSINFO_H +#include <sys/sysinfo.h> +#endif + +static void Jim_PosixSetError(Jim_Interp *interp) +{ + Jim_SetResultString(interp, strerror(errno), -1); +} + +#if defined(HAVE_FORK) +static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + pid_t pid; + + JIM_NOTUSED(argv); + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + if ((pid = fork()) == -1) { + Jim_PosixSetError(interp); + return JIM_ERR; + } + Jim_SetResultInt(interp, (jim_wide) pid); + return JIM_OK; +} +#endif + +/* + * os.wait ?-nohang? pid + * + * An interface to waitpid(2) + * + * Returns a 3 element list. + * + * If -nohang is specified, and the process is still alive, returns + * + * {0 none 0} + * + * If the process does not exist or has already been waited for, returns: + * + * {-1 error <error-description>} + * + * If the process exited normally, returns: + * + * {<pid> exit <exit-status>} + * + * If the process terminated on a signal, returns: + * + * {<pid> signal <signal-number>} + * + * Otherwise (core dump, stopped, continued, ...), returns: + * + * {<pid> other 0} + */ +static int Jim_PosixWaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int nohang = 0; + long pid; + int status; + Jim_Obj *listObj; + const char *type; + int value; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { + nohang = 1; + } + if (argc != nohang + 2) { + Jim_WrongNumArgs(interp, 1, argv, "?-nohang? pid"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) { + return JIM_ERR; + } + + pid = waitpid(pid, &status, nohang ? WNOHANG : 0); + listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pid)); + if (pid < 0) { + type = "error"; + value = errno; + } + else if (pid == 0) { + type = "none"; + value = 0; + } + else if (WIFEXITED(status)) { + type = "exit"; + value = WEXITSTATUS(status); + } + else if (WIFSIGNALED(status)) { + type = "signal"; + value = WTERMSIG(status); + } + else { + type = "other"; + value = 0; + } + + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, type, -1)); + if (pid < 0) { + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, strerror(value), -1)); + } + else { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); + } + Jim_SetResult(interp, listObj); + return JIM_OK; +} + +static int Jim_PosixGetidsCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objv[8]; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + objv[0] = Jim_NewStringObj(interp, "uid", -1); + objv[1] = Jim_NewIntObj(interp, getuid()); + objv[2] = Jim_NewStringObj(interp, "euid", -1); + objv[3] = Jim_NewIntObj(interp, geteuid()); + objv[4] = Jim_NewStringObj(interp, "gid", -1); + objv[5] = Jim_NewIntObj(interp, getgid()); + objv[6] = Jim_NewStringObj(interp, "egid", -1); + objv[7] = Jim_NewIntObj(interp, getegid()); + Jim_SetResult(interp, Jim_NewListObj(interp, objv, 8)); + return JIM_OK; +} + +#define JIM_HOST_NAME_MAX 1024 +static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *buf; + int rc = JIM_OK; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + buf = Jim_Alloc(JIM_HOST_NAME_MAX); + if (gethostname(buf, JIM_HOST_NAME_MAX) == -1) { + Jim_PosixSetError(interp); + rc = JIM_ERR; + } + else { + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, -1)); + } + return rc; +} + +static int Jim_PosixUptimeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_STRUCT_SYSINFO_UPTIME + struct sysinfo info; + + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + + if (sysinfo(&info) == -1) { + Jim_PosixSetError(interp); + return JIM_ERR; + } + + Jim_SetResultInt(interp, info.uptime); +#else + Jim_SetResultInt(interp, (long)time(NULL)); +#endif + return JIM_OK; +} + +static int Jim_PosixPidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + + Jim_SetResultInt(interp, getpid()); + return JIM_OK; +} + +int Jim_posixInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "posix", "1.0", JIM_ERRMSG)) + return JIM_ERR; + +#ifdef HAVE_FORK + Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); +#endif + Jim_CreateCommand(interp, "os.wait", Jim_PosixWaitCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.gethostname", Jim_PosixGethostnameCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.uptime", Jim_PosixUptimeCommand, NULL, NULL); + Jim_CreateCommand(interp, "pid", Jim_PosixPidCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c new file mode 100755 index 0000000..67fc956 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readdir.c @@ -0,0 +1,119 @@ + +/* + * Tcl readdir command. + * + * (c) 2008 Steve Bennett <steveb@worware.net.au> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on original work by: + *----------------------------------------------------------------------------- + * Copyright 1991-1994 Karl Lehenbauer and Mark Diekhans. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies. Karl Lehenbauer and + * Mark Diekhans make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + *----------------------------------------------------------------------------- + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <dirent.h> + +#include "jim.h" +#include "jimautoconf.h" + +/* + *----------------------------------------------------------------------------- + * + * Jim_ReaddirCmd -- + * Implements the rename TCL command: + * readdir ?-nocomplain? dirPath + * + * Results: + * Standard TCL result. + *----------------------------------------------------------------------------- + */ +int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *dirPath; + DIR *dirPtr; + struct dirent *entryPtr; + int nocomplain = 0; + + if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) { + nocomplain = 1; + } + if (argc != 2 && !nocomplain) { + Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath"); + return JIM_ERR; + } + + dirPath = Jim_String(argv[1 + nocomplain]); + + dirPtr = opendir(dirPath); + if (dirPtr == NULL) { + if (nocomplain) { + return JIM_OK; + } + Jim_SetResultString(interp, strerror(errno), -1); + return JIM_ERR; + } + Jim_SetResultString(interp, strerror(errno), -1); + + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + + while ((entryPtr = readdir(dirPtr)) != NULL) { + if (entryPtr->d_name[0] == '.') { + if (entryPtr->d_name[1] == '\0') { + continue; + } + if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) + continue; + } + Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, + entryPtr->d_name, -1)); + } + closedir(dirPtr); + + return JIM_OK; +} + +int Jim_readdirInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readline.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readline.c new file mode 100755 index 0000000..3990d0c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-readline.c @@ -0,0 +1,61 @@ + +/* Jim - Readline bindings for Jim + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jim.h" +#include "jimautoconf.h" + +#include <readline/readline.h> +#include <readline/history.h> + +static int JimRlReadlineCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *line; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "prompt"); + return JIM_ERR; + } + line = readline(Jim_String(argv[1])); + if (!line) { + return JIM_EXIT; + } + Jim_SetResult(interp, Jim_NewStringObj(interp, line, -1)); + return JIM_OK; +} + +static int JimRlAddHistoryCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "string"); + return JIM_ERR; + } + add_history(Jim_String(argv[1])); + return JIM_OK; +} + +int Jim_readlineInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "readline", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "readline.readline", JimRlReadlineCommand, NULL, NULL); + Jim_CreateCommand(interp, "readline.addhistory", JimRlAddHistoryCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c new file mode 100755 index 0000000..2ccd996 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-regexp.c @@ -0,0 +1,566 @@ +/* + * Implements the regexp and regsub commands for Jim + * + * (c) 2008 Steve Bennett <steveb@workware.net.au> + * + * Uses C library regcomp()/regexec() for the matching. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + * Based on code originally from Tcl 6.7: + * + * Copyright 1987-1991 Regents of the University of California + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jimregexp.h" + +static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + regfree(objPtr->internalRep.regexpValue.compre); + Jim_Free(objPtr->internalRep.regexpValue.compre); +} + +static const Jim_ObjType regexpObjType = { + "regexp", + FreeRegexpInternalRep, + NULL, + NULL, + JIM_TYPE_NONE +}; + +static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags) +{ + regex_t *compre; + const char *pattern; + int ret; + + /* Check if the object is already an uptodate variable */ + if (objPtr->typePtr == ®expObjType && + objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) { + /* nothing to do */ + return objPtr->internalRep.regexpValue.compre; + } + + /* Not a regexp or the flags do not match */ + + /* Get the string representation */ + pattern = Jim_String(objPtr); + compre = Jim_Alloc(sizeof(regex_t)); + + if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { + char buf[100]; + + regerror(ret, compre, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf); + regfree(compre); + Jim_Free(compre); + return NULL; + } + + Jim_FreeIntRep(interp, objPtr); + + objPtr->typePtr = ®expObjType; + objPtr->internalRep.regexpValue.flags = flags; + objPtr->internalRep.regexpValue.compre = compre; + + return compre; +} + +int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int opt_indices = 0; + int opt_all = 0; + int opt_inline = 0; + regex_t *regex; + int match, i, j; + int offset = 0; + regmatch_t *pmatch = NULL; + int source_len; + int result = JIM_OK; + const char *pattern; + const char *source_str; + int num_matches = 0; + int num_vars; + Jim_Obj *resultListObj = NULL; + int regcomp_flags = 0; + int eflags = 0; + int option; + enum { + OPT_INDICES, OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END + }; + static const char * const options[] = { + "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL + }; + + if (argc < 3) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_INDICES: + opt_indices = 1; + break; + + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_INLINE: + opt_inline = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i < 2) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + + pattern = Jim_String(argv[i]); + source_str = Jim_GetString(argv[i + 1], &source_len); + + num_vars = argc - i - 2; + + if (opt_inline) { + if (num_vars) { + Jim_SetResultString(interp, "regexp match variables not allowed when using -inline", + -1); + result = JIM_ERR; + goto done; + } + num_vars = regex->re_nsub + 1; + } + + pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch)); + + /* If an offset has been specified, adjust for that now. + * If it points past the end of the string, point to the terminating null + */ + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + source_str += source_len; + } + else if (offset > 0) { + source_str += offset; + } + eflags |= REG_NOTBOL; + } + + if (opt_inline) { + resultListObj = Jim_NewListObj(interp, NULL, 0); + } + + next_match: + match = regexec(regex, source_str, num_vars + 1, pmatch, eflags); + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + result = JIM_ERR; + goto done; + } + + if (match == REG_NOMATCH) { + goto done; + } + + num_matches++; + + if (opt_all && !opt_inline) { + /* Just count the number of matches, so skip the substitution h */ + goto try_next_match; + } + + /* + * If additional variable names have been specified, return + * index information in those variables. + */ + + j = 0; + for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) { + Jim_Obj *resultObj; + + if (opt_indices) { + resultObj = Jim_NewListObj(interp, NULL, 0); + } + else { + resultObj = Jim_NewStringObj(interp, "", 0); + } + + if (pmatch[j].rm_so == -1) { + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + } + } + else { + int len = pmatch[j].rm_eo - pmatch[j].rm_so; + + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so + len - 1)); + } + else { + Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len); + } + } + + if (opt_inline) { + Jim_ListAppendElement(interp, resultListObj, resultObj); + } + else { + /* And now set the result variable */ + result = Jim_SetVariable(interp, argv[i], resultObj); + + if (result != JIM_OK) { + Jim_FreeObj(interp, resultObj); + break; + } + } + } + + try_next_match: + if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) { + if (pmatch[0].rm_eo) { + offset += pmatch[0].rm_eo; + source_str += pmatch[0].rm_eo; + } + else { + source_str++; + offset++; + } + if (*source_str) { + eflags = REG_NOTBOL; + goto next_match; + } + } + + done: + if (result == JIM_OK) { + if (opt_inline) { + Jim_SetResult(interp, resultListObj); + } + else { + Jim_SetResultInt(interp, num_matches); + } + } + + Jim_Free(pmatch); + return result; +} + +#define MAX_SUB_MATCHES 50 + +int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int regcomp_flags = 0; + int regexec_flags = 0; + int opt_all = 0; + int offset = 0; + regex_t *regex; + const char *p; + int result; + regmatch_t pmatch[MAX_SUB_MATCHES + 1]; + int num_matches = 0; + + int i, j, n; + Jim_Obj *varname; + Jim_Obj *resultObj; + const char *source_str; + int source_len; + const char *replace_str; + int replace_len; + const char *pattern; + int option; + enum { + OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END + }; + static const char * const options[] = { + "-nocase", "-line", "-all", "-start", "--", NULL + }; + + if (argc < 4) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string subSpec ?varName?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i != 3 && argc - i != 4) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + pattern = Jim_String(argv[i]); + + source_str = Jim_GetString(argv[i + 1], &source_len); + replace_str = Jim_GetString(argv[i + 2], &replace_len); + varname = argv[i + 3]; + + /* Create the result string */ + resultObj = Jim_NewStringObj(interp, "", 0); + + /* If an offset has been specified, adjust for that now. + * If it points past the end of the string, point to the terminating null + */ + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + offset = source_len; + } + else if (offset < 0) { + offset = 0; + } + } + + /* Copy the part before -start */ + Jim_AppendString(interp, resultObj, source_str, offset); + + /* + * The following loop is to handle multiple matches within the + * same source string; each iteration handles one match and its + * corresponding substitution. If "-all" hasn't been specified + * then the loop body only gets executed once. + */ + + n = source_len - offset; + p = source_str + offset; + do { + int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags); + + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + return JIM_ERR; + } + if (match == REG_NOMATCH) { + break; + } + + num_matches++; + + /* + * Copy the portion of the source string before the match to the + * result variable. + */ + Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so); + + /* + * Append the subSpec (replace_str) argument to the variable, making appropriate + * substitutions. This code is a bit hairy because of the backslash + * conventions and because the code saves up ranges of characters in + * subSpec to reduce the number of calls to Jim_SetVar. + */ + + for (j = 0; j < replace_len; j++) { + int idx; + int c = replace_str[j]; + + if (c == '&') { + idx = 0; + } + else if (c == '\\' && j < replace_len) { + c = replace_str[++j]; + if ((c >= '0') && (c <= '9')) { + idx = c - '0'; + } + else if ((c == '\\') || (c == '&')) { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + else { + Jim_AppendString(interp, resultObj, replace_str + j - 1, 2); + continue; + } + } + else { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) { + Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so, + pmatch[idx].rm_eo - pmatch[idx].rm_so); + } + } + + p += pmatch[0].rm_eo; + n -= pmatch[0].rm_eo; + + /* If -all is not specified, or there is no source left, we are done */ + if (!opt_all || n == 0) { + break; + } + + /* An anchored pattern without -line must be done */ + if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { + break; + } + + /* If the pattern is empty, need to step forwards */ + if (pattern[0] == '\0' && n) { + /* Need to copy the char we are moving over */ + Jim_AppendString(interp, resultObj, p, 1); + p++; + n--; + } + + regexec_flags |= REG_NOTBOL; + } while (n); + + /* + * Copy the portion of the string after the last match to the + * result variable. + */ + Jim_AppendString(interp, resultObj, p, -1); + + /* And now set or return the result variable */ + if (argc - i == 4) { + result = Jim_SetVariable(interp, varname, resultObj); + + if (result == JIM_OK) { + Jim_SetResultInt(interp, num_matches); + } + else { + Jim_FreeObj(interp, resultObj); + } + } + else { + Jim_SetResult(interp, resultObj); + result = JIM_OK; + } + + return result; +} + +int Jim_regexpInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL); + Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c new file mode 100755 index 0000000..2e700eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-sdl.c @@ -0,0 +1,234 @@ + +/* Jim - SDL extension + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <SDL/SDL.h> +#include <SDL/SDL_gfxPrimitives.h> + +#include "jim.h" +#include "jimautoconf.h" + +#define AIO_CMD_LEN 128 + +typedef struct JimSdlSurface +{ + SDL_Surface *screen; +} JimSdlSurface; + +static void JimSdlSetError(Jim_Interp *interp) +{ + Jim_SetResultString(interp, SDL_GetError(), -1); +} + +static void JimSdlDelProc(Jim_Interp *interp, void *privData) +{ + JimSdlSurface *jss = privData; + + JIM_NOTUSED(interp); + + SDL_FreeSurface(jss->screen); + Jim_Free(jss); +} + +/* Calls to commands created via [sdl.surface] are implemented by this + * C command. */ +static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss = Jim_CmdPrivData(interp); + int option; + static const char * const options[] = { + "free", "flip", "pixel", "rectangle", "box", "line", "aaline", + "circle", "aacircle", "fcircle", NULL + }; + enum + { OPT_FREE, OPT_FLIP, OPT_PIXEL, OPT_RECTANGLE, OPT_BOX, OPT_LINE, + OPT_AALINE, OPT_CIRCLE, OPT_AACIRCLE, OPT_FCIRCLE + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, "SDL surface method", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + if (option == OPT_PIXEL) { + /* PIXEL */ + long x, y, red, green, blue, alpha = 255; + + if (argc != 7 && argc != 8) { + Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || + Jim_GetLong(interp, argv[3], &y) != JIM_OK || + Jim_GetLong(interp, argv[4], &red) != JIM_OK || + Jim_GetLong(interp, argv[5], &green) != JIM_OK || + Jim_GetLong(interp, argv[6], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 8 && Jim_GetLong(interp, argv[7], &alpha) != JIM_OK) + return JIM_ERR; + pixelRGBA(jss->screen, x, y, red, green, blue, alpha); + return JIM_OK; + } + else if (option == OPT_RECTANGLE || option == OPT_BOX || + option == OPT_LINE || option == OPT_AALINE) { + /* RECTANGLE, BOX, LINE, AALINE */ + long x1, y1, x2, y2, red, green, blue, alpha = 255; + + if (argc != 9 && argc != 10) { + Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x1) != JIM_OK || + Jim_GetLong(interp, argv[3], &y1) != JIM_OK || + Jim_GetLong(interp, argv[4], &x2) != JIM_OK || + Jim_GetLong(interp, argv[5], &y2) != JIM_OK || + Jim_GetLong(interp, argv[6], &red) != JIM_OK || + Jim_GetLong(interp, argv[7], &green) != JIM_OK || + Jim_GetLong(interp, argv[8], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 10 && Jim_GetLong(interp, argv[9], &alpha) != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_RECTANGLE: + rectangleRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_BOX: + boxRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_LINE: + lineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + case OPT_AALINE: + aalineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); + break; + } + return JIM_OK; + } + else if (option == OPT_CIRCLE || option == OPT_AACIRCLE || option == OPT_FCIRCLE) { + /* CIRCLE, AACIRCLE, FCIRCLE */ + long x, y, radius, red, green, blue, alpha = 255; + + if (argc != 8 && argc != 9) { + Jim_WrongNumArgs(interp, 2, argv, "x y radius red green blue ?alpha?"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || + Jim_GetLong(interp, argv[3], &y) != JIM_OK || + Jim_GetLong(interp, argv[4], &radius) != JIM_OK || + Jim_GetLong(interp, argv[5], &red) != JIM_OK || + Jim_GetLong(interp, argv[6], &green) != JIM_OK || + Jim_GetLong(interp, argv[7], &blue) != JIM_OK) { + return JIM_ERR; + } + if (argc == 9 && Jim_GetLong(interp, argv[8], &alpha) != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_CIRCLE: + circleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + case OPT_AACIRCLE: + aacircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + case OPT_FCIRCLE: + filledCircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); + break; + } + return JIM_OK; + } + else if (option == OPT_FREE) { + /* FREE */ + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + Jim_DeleteCommand(interp, Jim_String(argv[0])); + return JIM_OK; + } + else if (option == OPT_FLIP) { + /* FLIP */ + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + SDL_Flip(jss->screen); + return JIM_OK; + } + return JIM_OK; +} + +static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + JimSdlSurface *jss; + char buf[AIO_CMD_LEN]; + Jim_Obj *objPtr; + long screenId, xres, yres; + SDL_Surface *screen; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "xres yres"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK || + Jim_GetLong(interp, argv[2], &yres) != JIM_OK) + return JIM_ERR; + + /* Try to create the surface */ + screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT); + if (screen == NULL) { + JimSdlSetError(interp); + return JIM_ERR; + } + /* Get the next file id */ + if (Jim_EvalGlobal(interp, "if {[catch {incr sdl.surfaceId}]} {set sdl.surfaceId 0}") != JIM_OK) + return JIM_ERR; + objPtr = Jim_GetVariableStr(interp, "sdl.surfaceId", JIM_ERRMSG); + if (objPtr == NULL) + return JIM_ERR; + if (Jim_GetLong(interp, objPtr, &screenId) != JIM_OK) + return JIM_ERR; + + /* Create the SDL screen command */ + jss = Jim_Alloc(sizeof(*jss)); + jss->screen = screen; + sprintf(buf, "sdl.surface%ld", screenId); + Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; +} + +int Jim_sdlInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + JimSdlSetError(interp); + return JIM_ERR; + } + atexit(SDL_Quit); + Jim_CreateCommand(interp, "sdl.screen", JimSdlSurfaceCommand, NULL, NULL); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.c new file mode 100755 index 0000000..6a2a2be --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.c @@ -0,0 +1,514 @@ + +/* + * jim-signal.c + * + */ + +#include <signal.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jim-subcmd.h" +#include "jim-signal.h" + +#define MAX_SIGNALS (sizeof(jim_wide) * 8) + +static jim_wide *sigloc; +static jim_wide sigsblocked; +static struct sigaction *sa_old; +static int signal_handling[MAX_SIGNALS]; + +/* Make sure to do this as a wide, not int */ +#define sig_to_bit(SIG) ((jim_wide)1 << (SIG)) + +static void signal_handler(int sig) +{ + /* We just remember which signals occurred. Jim_Eval() will + * notice this as soon as it can and throw an error + */ + *sigloc |= sig_to_bit(sig); +} + +static void signal_ignorer(int sig) +{ + /* We just remember which signals occurred */ + sigsblocked |= sig_to_bit(sig); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SignalId -- + * + * Return a textual identifier for a signal number. + * + * Results: + * This procedure returns a machine-readable textual identifier + * that corresponds to sig. The identifier is the same as the + * #define name in signal.h. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +#define CHECK_SIG(NAME) if (sig == NAME) return #NAME + +const char *Jim_SignalId(int sig) +{ + CHECK_SIG(SIGABRT); + CHECK_SIG(SIGALRM); + CHECK_SIG(SIGBUS); + CHECK_SIG(SIGCHLD); + CHECK_SIG(SIGCONT); + CHECK_SIG(SIGFPE); + CHECK_SIG(SIGHUP); + CHECK_SIG(SIGILL); + CHECK_SIG(SIGINT); +#ifdef SIGIO + CHECK_SIG(SIGIO); +#endif + CHECK_SIG(SIGKILL); + CHECK_SIG(SIGPIPE); + CHECK_SIG(SIGPROF); + CHECK_SIG(SIGQUIT); + CHECK_SIG(SIGSEGV); + CHECK_SIG(SIGSTOP); + CHECK_SIG(SIGSYS); + CHECK_SIG(SIGTERM); + CHECK_SIG(SIGTRAP); + CHECK_SIG(SIGTSTP); + CHECK_SIG(SIGTTIN); + CHECK_SIG(SIGTTOU); + CHECK_SIG(SIGURG); + CHECK_SIG(SIGUSR1); + CHECK_SIG(SIGUSR2); + CHECK_SIG(SIGVTALRM); + CHECK_SIG(SIGWINCH); + CHECK_SIG(SIGXCPU); + CHECK_SIG(SIGXFSZ); +#ifdef SIGPWR + CHECK_SIG(SIGPWR); +#endif +#ifdef SIGCLD + CHECK_SIG(SIGCLD); +#endif +#ifdef SIGEMT + CHECK_SIG(SIGEMT); +#endif +#ifdef SIGLOST + CHECK_SIG(SIGLOST); +#endif +#ifdef SIGPOLL + CHECK_SIG(SIGPOLL); +#endif +#ifdef SIGINFO + CHECK_SIG(SIGINFO); +#endif + return "unknown signal"; +} + +const char *Jim_SignalName(int sig) +{ +#ifdef HAVE_SYS_SIGLIST + if (sig >= 0 && sig < NSIG) { + return sys_siglist[sig]; + } +#endif + return Jim_SignalId(sig); +} + +/** + * Given the name of a signal, returns the signal value if found, + * or returns -1 (and sets an error) if not found. + * We accept -SIGINT, SIGINT, INT or any lowercase version or a number, + * either positive or negative. + */ +static int find_signal_by_name(Jim_Interp *interp, const char *name) +{ + int i; + const char *pt = name; + + /* Remove optional - and SIG from the front of the name */ + if (*pt == '-') { + pt++; + } + if (strncasecmp(name, "sig", 3) == 0) { + pt += 3; + } + if (isdigit(UCHAR(pt[0]))) { + i = atoi(pt); + if (i > 0 && i < MAX_SIGNALS) { + return i; + } + } + else { + for (i = 1; i < MAX_SIGNALS; i++) { + /* Jim_SignalId() returns names such as SIGINT, and + * returns "unknown signal id" if unknown, so this will work + */ + if (strcasecmp(Jim_SignalId(i) + 3, pt) == 0) { + return i; + } + } + } + Jim_SetResultString(interp, "unknown signal ", -1); + Jim_AppendString(interp, Jim_GetResult(interp), name, -1); + + return -1; +} + +#define SIGNAL_ACTION_HANDLE 1 +#define SIGNAL_ACTION_IGNORE -1 +#define SIGNAL_ACTION_DEFAULT 0 + +static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *const *argv) +{ + struct sigaction sa; + int i; + + if (argc == 0) { + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (i = 1; i < MAX_SIGNALS; i++) { + if (signal_handling[i] == action) { + /* Add signal name to the list */ + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, Jim_SignalId(i), -1)); + } + } + return JIM_OK; + } + + /* Catch all the signals we care about */ + if (action != SIGNAL_ACTION_DEFAULT) { + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (action == SIGNAL_ACTION_HANDLE) { + sa.sa_handler = signal_handler; + } + else { + sa.sa_handler = signal_ignorer; + } + } + + /* Iterate through the provided signals */ + for (i = 0; i < argc; i++) { + int sig = find_signal_by_name(interp, Jim_String(argv[i])); + + if (sig < 0) { + return JIM_ERR; + } + if (action != signal_handling[sig]) { + /* Need to change the action for this signal */ + switch (action) { + case SIGNAL_ACTION_HANDLE: + case SIGNAL_ACTION_IGNORE: + if (signal_handling[sig] == SIGNAL_ACTION_DEFAULT) { + if (!sa_old) { + /* Allocate the structure the first time through */ + sa_old = Jim_Alloc(sizeof(*sa_old) * MAX_SIGNALS); + } + sigaction(sig, &sa, &sa_old[sig]); + } + else { + sigaction(sig, &sa, 0); + } + break; + + case SIGNAL_ACTION_DEFAULT: + /* Restore old handler */ + if (sa_old) { + sigaction(sig, &sa_old[sig], 0); + } + } + signal_handling[sig] = action; + } + } + + return JIM_OK; +} + +static int signal_cmd_handle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_HANDLE, argc, argv); +} + +static int signal_cmd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_IGNORE, argc, argv); +} + +static int signal_cmd_default(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_DEFAULT, argc, argv); +} + +static int signal_set_sigmask_result(Jim_Interp *interp, jim_wide sigmask) +{ + int i; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < MAX_SIGNALS; i++) { + if (sigmask & sig_to_bit(i)) { + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, Jim_SignalId(i), -1)); + } + } + Jim_SetResult(interp, listObj); + return JIM_OK; +} + +static int signal_cmd_check(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int clear = 0; + jim_wide mask = 0; + jim_wide blocked; + + if (argc > 0 && Jim_CompareStringImmediate(interp, argv[0], "-clear")) { + clear++; + } + if (argc > clear) { + int i; + + /* Signals specified */ + for (i = clear; i < argc; i++) { + int sig = find_signal_by_name(interp, Jim_String(argv[i])); + + if (sig < 0 || sig >= MAX_SIGNALS) { + return -1; + } + mask |= sig_to_bit(sig); + } + } + else { + /* No signals specified, so check/clear all */ + mask = ~mask; + } + + if ((sigsblocked & mask) == 0) { + /* No matching signals, so empty result and nothing to do */ + return JIM_OK; + } + /* Be careful we don't have a race condition where signals are cleared but not returned */ + blocked = sigsblocked & mask; + if (clear) { + sigsblocked &= ~blocked; + } + /* Set the result */ + signal_set_sigmask_result(interp, blocked); + return JIM_OK; +} + +static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig = SIGINT; + + if (argc == 1) { + if ((sig = find_signal_by_name(interp, Jim_String(argv[0]))) < 0) { + return JIM_ERR; + } + } + + /* If the signal is ignored (blocked) ... */ + if (signal_handling[sig] == SIGNAL_ACTION_IGNORE) { + sigsblocked |= sig_to_bit(sig); + return JIM_OK; + } + + /* Just set the signal */ + interp->sigmask |= sig_to_bit(sig); + + /* Set the canonical name of the signal as the result */ + Jim_SetResultString(interp, Jim_SignalId(sig), -1); + + /* And simply say we caught the signal */ + return JIM_SIGNAL; +} + +/* + *----------------------------------------------------------------------------- + * + * Jim_SignalCmd -- + * Implements the TCL signal command: + * signal handle|ignore|default|throw ?signals ...? + * signal throw signal + * + * Specifies which signals are handled by Tcl code. + * If the one of the given signals is caught, it causes a JIM_SIGNAL + * exception to be thrown which can be caught by catch. + * + * Use 'signal ignore' to ignore the signal(s) + * Use 'signal default' to go back to the default behaviour + * Use 'signal throw signal' to raise the given signal + * + * If no arguments are given, returns the list of signals which are being handled + * + * Results: + * Standard TCL results. + * + *----------------------------------------------------------------------------- + */ +static const jim_subcmd_type signal_command_table[] = { + { .cmd = "handle", + .args = "?signals ...?", + .function = signal_cmd_handle, + .minargs = 0, + .maxargs = -1, + .description = "Lists handled signals, or adds to handled signals" + }, + { .cmd = "ignore", + .args = "?signals ...?", + .function = signal_cmd_ignore, + .minargs = 0, + .maxargs = -1, + .description = "Lists ignored signals, or adds to ignored signals" + }, + { .cmd = "default", + .args = "?signals ...?", + .function = signal_cmd_default, + .minargs = 0, + .maxargs = -1, + .description = "Lists defaulted signals, or adds to defaulted signals" + }, + { .cmd = "check", + .args = "?-clear? ?signals ...?", + .function = signal_cmd_check, + .minargs = 0, + .maxargs = -1, + .description = "Returns ignored signals which have occurred, and optionally clearing them" + }, + { .cmd = "throw", + .args = "?signal?", + .function = signal_cmd_throw, + .minargs = 0, + .maxargs = 1, + .description = "Raises the given signal (default SIGINT)" + }, + { 0 } +}; + +static int Jim_AlarmCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { +#ifdef HAVE_UALARM + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { + if (t < 1) { + ualarm(t * 1e6, 0); + } + else { + alarm(t); + } + } +#else + long t; + + ret = Jim_GetLong(interp, argv[1], &t); + if (ret == JIM_OK) { + alarm(t); + } +#endif + } + + return ret; +} + +static int Jim_SleepCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { +#ifdef HAVE_USLEEP + if (t < 1) { + usleep(t * 1e6); + } + else +#endif + sleep(t); + } + } + + return ret; +} + +static int Jim_KillCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig; + long pid; + Jim_Obj *pidObj; + const char *signame; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?SIG|-0? pid"); + return JIM_ERR; + } + + if (argc == 2) { + signame = "SIGTERM"; + pidObj = argv[1]; + } + else { + signame = Jim_String(argv[1]); + pidObj = argv[2]; + } + + /* Special 'kill -0 pid' to determine if a pid exists */ + if (strcmp(signame, "-0") == 0 || strcmp(signame, "0") == 0) { + sig = 0; + } + else { + sig = find_signal_by_name(interp, signame); + if (sig < 0) { + return JIM_ERR; + } + } + + if (Jim_GetLong(interp, pidObj, &pid) != JIM_OK) { + return JIM_ERR; + } + + if (kill(pid, sig) == 0) { + return JIM_OK; + } + + Jim_SetResultString(interp, "kill: Failed to deliver signal", -1); + return JIM_ERR; +} + +int Jim_signalInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "signal", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + /* Teach the jim core how to set a result from a sigmask */ + interp->signal_set_result = signal_set_sigmask_result; + + /* Make sure we know where to store the signals which occur */ + sigloc = &interp->sigmask; + + Jim_CreateCommand(interp, "signal", Jim_SubCmdProc, (void *)signal_command_table, NULL); + Jim_CreateCommand(interp, "alarm", Jim_AlarmCmd, 0, 0); + Jim_CreateCommand(interp, "kill", Jim_KillCmd, 0, 0); + + /* Sleep is slightly dubious here */ + Jim_CreateCommand(interp, "sleep", Jim_SleepCmd, 0, 0); + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.h new file mode 100755 index 0000000..92e080d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-signal.h @@ -0,0 +1,24 @@ +#ifndef JIM_SIGNAL_H +#define JIM_SIGNAL_H + +/* + *---------------------------------------------------------------------- + * + * Tcl_SignalId -- + * + * Return a textual identifier for a signal number. + * + * Results: + * This procedure returns a machine-readable textual identifier + * that corresponds to sig. The identifier is the same as the + * #define name in signal.h. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +const char *Jim_SignalId(int sig); +const char *Jim_SignalName(int sig); + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c new file mode 100755 index 0000000..2de560a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.c @@ -0,0 +1,293 @@ +#include <stdio.h> +#include <string.h> + +#include "jim-subcmd.h" +#include "jimautoconf.h" + +/** + * Implements the common 'commands' subcommand + */ +static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + /* Nothing to do, since the result has already been created */ + return JIM_OK; +} + +/** + * Do-nothing command to support -commands and -usage + */ +static const jim_subcmd_type dummy_subcmd = { + .cmd = "dummy", + .function = subcmd_null, + .flags = JIM_MODFLAG_HIDDEN, +}; + +static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep) +{ + const char *s = ""; + + for (; ct->cmd; ct++) { + if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { + Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL); + s = sep; + } + } +} + +static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, + Jim_Obj *cmd, Jim_Obj *subcmd) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type, + " command \"", Jim_String(subcmd), "\": should be ", NULL); + add_commands(interp, command_table, ", "); +} + +static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, + Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), + " command ... \", where command is one of: ", NULL); + add_commands(interp, command_table, ", "); +} + +static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) +{ + if (cmd) { + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL); + if (ct->args && *ct->args) { + Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL); + } +} + +static void show_full_usage(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, + Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + for (; ct->cmd; ct++) { + if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + if (ct->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n ", ct->description, NULL); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", NULL); + } + } +} + +static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) +{ + Jim_SetResultString(interp, "wrong # args: must be \"", -1); + add_cmd_usage(interp, command_table, subcmd); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); +} + +const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, + int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct; + const jim_subcmd_type *partial = 0; + int cmdlen; + Jim_Obj *cmd; + const char *cmdstr; + const char *cmdname; + int help = 0; + + cmdname = Jim_String(argv[0]); + + if (argc < 2) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, + " command ...\"\n", NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help\" or \"", + cmdname, " -help command\" for help", NULL); + return 0; + } + + cmd = argv[1]; + + if (argc == 2 && Jim_CompareStringImmediate(interp, cmd, "-usage")) { + /* Show full usage */ + show_full_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + + /* Check for the help command */ + if (Jim_CompareStringImmediate(interp, cmd, "-help")) { + if (argc == 2) { + /* Usage for the command, not the subcommand */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + help = 1; + + /* Skip the 'help' command */ + cmd = argv[2]; + } + + /* Check for special builtin '-commands' command first */ + if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { + /* Build the result here */ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + add_commands(interp, command_table, " "); + return &dummy_subcmd; + } + + cmdstr = Jim_GetString(cmd, &cmdlen); + + for (ct = command_table; ct->cmd; ct++) { + if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { + /* Found an exact match */ + break; + } + if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { + if (partial) { + /* Ambiguous */ + if (help) { + /* Just show the top level help here */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); + return 0; + } + partial = ct; + } + continue; + } + + /* If we had an unambiguous partial match */ + if (partial && !ct->cmd) { + ct = partial; + } + + if (!ct->cmd) { + /* No matching command */ + if (help) { + /* Just show the top level help here */ + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); + return 0; + } + + if (help) { + Jim_SetResultString(interp, "Usage: ", -1); + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + if (ct->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", ct->description, NULL); + } + return &dummy_subcmd; + } + + /* Check the number of args */ + if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { + Jim_SetResultString(interp, "wrong # args: must be \"", -1); + /* subcmd */ + add_cmd_usage(interp, ct, argv[0]); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); + + return 0; + } + + /* Good command */ + return ct; +} + +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) +{ + int ret = JIM_ERR; + + if (ct) { + if (ct->flags & JIM_MODFLAG_FULLARGV) { + ret = ct->function(interp, argc, argv); + } + else { + ret = ct->function(interp, argc - 2, argv + 2); + } + if (ret < 0) { + set_wrong_args(interp, ct, argv[0]); + ret = JIM_ERR; + } + } + return ret; +} + +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct = + Jim_ParseSubCmd(interp, (const jim_subcmd_type *)Jim_CmdPrivData(interp), argc, argv); + + return Jim_CallSubCmd(interp, ct, argc, argv); +} + +/* The following two functions are for normal commands */ +int +Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, + Jim_Obj *const *argv) +{ + /* -usage or -help */ + if (argc == 2) { + if (Jim_CompareStringImmediate(interp, argv[1], "-usage") + || Jim_CompareStringImmediate(interp, argv[1], "-help")) { + Jim_SetResultString(interp, "Usage: ", -1); + add_cmd_usage(interp, command_table, NULL); + if (command_table->description) { + Jim_AppendStrings(interp, Jim_GetResult(interp), "\n\n", command_table->description, + NULL); + } + return JIM_OK; + } + } + if (argc >= 2 && command_table->function) { + /* This is actually a sub command table */ + + Jim_Obj *nargv[4]; + int nargc = 0; + const char *subcmd = NULL; + + if (Jim_CompareStringImmediate(interp, argv[1], "-subcommands")) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + add_commands(interp, (jim_subcmd_type *) command_table->function, " "); + return JIM_OK; + } + + if (Jim_CompareStringImmediate(interp, argv[1], "-subhelp") + || Jim_CompareStringImmediate(interp, argv[1], "-help")) { + subcmd = "-help"; + } + else if (Jim_CompareStringImmediate(interp, argv[1], "-subusage")) { + subcmd = "-usage"; + } + + if (subcmd) { + nargv[nargc++] = Jim_NewStringObj(interp, "$handle", -1); + nargv[nargc++] = Jim_NewStringObj(interp, subcmd, -1); + if (argc >= 3) { + nargv[nargc++] = argv[2]; + } + Jim_ParseSubCmd(interp, (jim_subcmd_type *) command_table->function, nargc, nargv); + Jim_FreeNewObj(interp, nargv[0]); + Jim_FreeNewObj(interp, nargv[1]); + return 0; + } + } + + /* Check the number of args */ + if (argc - 1 < command_table->minargs || (command_table->maxargs >= 0 + && argc - 1 > command_table->maxargs)) { + set_wrong_args(interp, command_table, NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\nUse \"", Jim_String(argv[0]), + " -help\" for help", NULL); + return JIM_ERR; + } + + /* Not usage, but passed arg checking */ + return -1; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h new file mode 100755 index 0000000..3a672eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-subcmd.h @@ -0,0 +1,92 @@ +/* Provides a common approach to implementing Tcl commands + * which implement subcommands + */ +#ifndef JIM_SUBCMD_H +#define JIM_SUBCMD_H + +#include <jim.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +#define JIM_MODFLAG_HIDDEN 0x0001 /* Don't show the subcommand in usage or commands */ +#define JIM_MODFLAG_FULLARGV 0x0002 /* Subcmd proc gets called with full argv */ + +/* Custom flags start at 0x0100 */ + +/** + * Returns JIM_OK if OK, JIM_ERR (etc.) on error, break, continue, etc. + * Returns -1 if invalid args. + */ +typedef int tclmod_cmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +typedef struct { + const char *cmd; /* Name of the (sub)command */ + const char *args; /* Textual description of allowed args */ + tclmod_cmd_function *function; /* Function implementing the subcommand */ + short minargs; /* Minimum required arguments */ + short maxargs; /* Maximum allowed arguments or -1 if no limit */ + unsigned flags; /* JIM_MODFLAG_... plus custom flags */ + const char *description; /* Description of the subcommand */ +} jim_subcmd_type; + +/** + * Looks up the appropriate subcommand in the given command table and return + * the command function which implements the subcommand. + * NULL will be returned and an appropriate error will be set if the subcommand or + * arguments are invalid. + * + * Typical usage is: + * { + * const jim_subcmd_type *ct = Jim_ParseSubCmd(interp, command_table, argc, argv); + * + * return Jim_CallSubCmd(interp, ct, argc, argv); + * } + * + */ +const jim_subcmd_type * +Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); + +/** + * Parses the args against the given command table and executes the subcommand if found + * or sets an appropriate error if the subcommand or arguments is invalid. + * + * Can be used directly with Jim_CreateCommand() where the ClientData is the command table. + * + * e.g. Jim_CreateCommand(interp, "mycmd", Jim_SubCmdProc, command_table, NULL); + */ +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +/** + * Invokes the given subcmd with the given args as returned + * by Jim_ParseSubCmd() + * + * If ct is NULL, returns JIM_ERR, leaving any message. + * Otherwise invokes ct->function + * + * If ct->function returns -1, sets an error message and returns JIM_ERR. + * Otherwise returns the result of ct->function. + */ +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv); + +/** + * Standard processing for a command. + * + * This does the '-help' and '-usage' check and the number of args checks. + * for a top level command against a single 'jim_subcmd_type' structure. + * + * Additionally, if command_table->function is set, it should point to a sub command table + * and '-subhelp ?subcmd?', '-subusage' and '-subcommands' are then also recognised. + * + * Returns 0 if user requested usage, -1 on arg error, 1 if OK to process. + */ +int +Jim_CheckCmdUsage(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c new file mode 100755 index 0000000..4e14910 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-syslog.c @@ -0,0 +1,190 @@ + +/* Syslog interface for tcl + * Copyright Victor Wagner <vitus@ice.ru> at + * http://www.ice.ru/~vitus/works/tcl.html#syslog + * + * Slightly modified by Steve Bennett <steveb@snapgear.com> + * Ported to Jim by Steve Bennett <steveb@workware.net.au> + */ +#include <syslog.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" + +typedef struct +{ + int logOpened; + int facility; + int options; + char ident[32]; +} SyslogInfo; + +#ifndef LOG_AUTHPRIV +# define LOG_AUTHPRIV LOG_AUTH +#endif + +static const char * const facilities[] = { + [LOG_AUTHPRIV] = "authpriv", + [LOG_CRON] = "cron", + [LOG_DAEMON] = "daemon", + [LOG_KERN] = "kernel", + [LOG_LPR] = "lpr", + [LOG_MAIL] = "mail", + [LOG_NEWS] = "news", + [LOG_SYSLOG] = "syslog", + [LOG_USER] = "user", + [LOG_UUCP] = "uucp", + [LOG_LOCAL0] = "local0", + [LOG_LOCAL1] = "local1", + [LOG_LOCAL2] = "local2", + [LOG_LOCAL3] = "local3", + [LOG_LOCAL4] = "local4", + [LOG_LOCAL5] = "local5", + [LOG_LOCAL6] = "local6", + [LOG_LOCAL7] = "local7", +}; + +static const char * const priorities[] = { + [LOG_EMERG] = "emerg", + [LOG_ALERT] = "alert", + [LOG_CRIT] = "crit", + [LOG_ERR] = "error", + [LOG_WARNING] = "warning", + [LOG_NOTICE] = "notice", + [LOG_INFO] = "info", + [LOG_DEBUG] = "debug", +}; + +/** + * Deletes the syslog command. + */ +static void Jim_SyslogCmdDelete(Jim_Interp *interp, void *privData) +{ + SyslogInfo *info = (SyslogInfo *) privData; + + if (info->logOpened) { + closelog(); + } + Jim_Free(info); +} + +/* Syslog_Log - + * implements syslog tcl command. General format: syslog ?options? level text + * options -facility -ident -options + * + * syslog ?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? text + */ +int Jim_SyslogCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int priority = LOG_INFO; + int i = 1; + SyslogInfo *info = Jim_CmdPrivData(interp); + + if (argc <= 1) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-facility cron|daemon|...? ?-ident string? ?-options int? ?debug|info|...? message"); + return JIM_ERR; + } + while (i < argc - 1) { + if (Jim_CompareStringImmediate(interp, argv[i], "-facility")) { + int entry = + Jim_FindByName(Jim_String(argv[i + 1]), facilities, + sizeof(facilities) / sizeof(*facilities)); + if (entry < 0) { + Jim_SetResultString(interp, "Unknown facility", -1); + return JIM_ERR; + } + if (info->facility != entry) { + info->facility = entry; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-options")) { + long tmp; + + if (Jim_GetLong(interp, argv[i + 1], &tmp) == JIM_ERR) { + return JIM_ERR; + } + info->options = tmp; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-ident")) { + strncpy(info->ident, Jim_String(argv[i + 1]), sizeof(info->ident)); + info->ident[sizeof(info->ident) - 1] = 0; + if (info->logOpened) { + closelog(); + info->logOpened = 0; + } + } + else { + break; + } + i += 2; + } + + /* There should be either 0, 1 or 2 args left */ + if (i == argc) { + /* No args, but they have set some options, so OK */ + return JIM_OK; + } + + if (i < argc - 1) { + priority = + Jim_FindByName(Jim_String(argv[i]), priorities, + sizeof(priorities) / sizeof(*priorities)); + if (priority < 0) { + Jim_SetResultString(interp, "Unknown priority", -1); + return JIM_ERR; + } + i++; + } + + if (i != argc - 1) { + goto wrongargs; + } + if (!info->logOpened) { + if (!info->ident[0]) { + Jim_Obj *argv0 = Jim_GetGlobalVariableStr(interp, "argv0", JIM_NONE); + + if (argv0) { + strncpy(info->ident, Jim_String(argv0), sizeof(info->ident)); + } + else { + strcpy(info->ident, "Tcl script"); + } + info->ident[sizeof(info->ident) - 1] = 0; + } + openlog(info->ident, info->options, info->facility); + info->logOpened = 1; + } + syslog(priority, "%s", Jim_String(argv[i])); + + return JIM_OK; +} + +int Jim_syslogInit(Jim_Interp *interp) +{ + SyslogInfo *info; + + if (Jim_PackageProvide(interp, "syslog", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + info = Jim_Alloc(sizeof(*info)); + + info->logOpened = 0; + info->options = 0; + info->facility = LOG_USER; + info->ident[0] = 0; + + Jim_CreateCommand(interp, "syslog", Jim_SyslogCmd, info, Jim_SyslogCmdDelete); + + return JIM_OK; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h new file mode 100755 index 0000000..89e01f5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim-win32compat.h @@ -0,0 +1,69 @@ +#ifndef JIM_WIN32COMPAT_H +#define JIM_WIN32COMPAT_H + +/* Compatibility for Windows (mingw and msvc, not cygwin */ + +/* Note that at this point we don't yet have access to jimautoconf.h */ +#if defined(_WIN32) || defined(WIN32) +#ifndef STRICT + #define STRICT +#endif +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define HAVE_DLOPEN +void *dlopen(const char *path, int mode); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); +char *dlerror(void); + +#ifdef _MSC_VER +/* These are msvc vs gcc */ + +#if _MSC_VER >= 1000 + #pragma warning(disable:4146) +#endif + +#define strcasecmp _stricmp + +#define jim_wide _int64 +#ifndef LLONG_MAX + #define LLONG_MAX 9223372036854775807I64 +#endif +#ifndef LLONG_MIN + #define LLONG_MIN (-LLONG_MAX - 1I64) +#endif +#define JIM_WIDE_MIN LLONG_MIN +#define JIM_WIDE_MAX LLONG_MAX +#define JIM_WIDE_MODIFIER "I64d" + +#include <io.h> + +#define HAVE_GETTIMEOFDAY +struct timeval { + long tv_sec; + long tv_usec; +}; + +int gettimeofday(struct timeval *tv, void *unused); + +#define HAVE_OPENDIR +struct dirent { + char *d_name; +}; + +typedef struct DIR { + long handle; /* -1 for failed rewind */ + struct _finddata_t info; + struct dirent result; /* d_name null iff first time */ + char *name; /* null-terminated char string */ +} DIR; + +DIR *opendir(const char *name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); +#endif /* _MSC_VER */ + +#endif /* WIN32 */ + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.c new file mode 100755 index 0000000..8543de4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.c @@ -0,0 +1,14478 @@ + +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008,2009 oharboe - Øyvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * Copyright 2008 Steve Bennett <steveb@workware.net.au> + * Copyright 2009 Nico Coesel <ncoesel@dealogic.nl> + * Copyright 2009 Zachary T Welch zw@superlucidity.net + * Copyright 2009 David Brownell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + **/ +#define JIM_OPTIMIZATION /* comment to avoid optimizations and reduce size */ + +#include <stdio.h> +#include <stdlib.h> + +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> +#include <assert.h> +#include <errno.h> +#include <time.h> +#include <setjmp.h> + +#include <unistd.h> +#include <sys/time.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "utf8.h" + +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif +#ifdef HAVE_CRT_EXTERNS_H +#include <crt_externs.h> +#endif + +/* For INFINITY, even if math functions are not enabled */ +#include <math.h> + +/* We may decide to switch to using $[...] after all, so leave it as an option */ +/*#define EXPRSUGAR_BRACKET*/ + +/* For the no-autoconf case */ +#ifndef TCL_LIBRARY +#define TCL_LIBRARY "." +#endif +#ifndef TCL_PLATFORM_OS +#define TCL_PLATFORM_OS "unknown" +#endif +#ifndef TCL_PLATFORM_PLATFORM +#define TCL_PLATFORM_PLATFORM "unknown" +#endif +#ifndef TCL_PLATFORM_PATH_SEPARATOR +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#endif + +/*#define DEBUG_SHOW_SCRIPT*/ +/*#define DEBUG_SHOW_SCRIPT_TOKENS*/ +/*#define DEBUG_SHOW_SUBST*/ +/*#define DEBUG_SHOW_EXPR*/ +/*#define DEBUG_SHOW_EXPR_TOKENS*/ +/*#define JIM_DEBUG_GC*/ +#ifdef JIM_MAINTAINER +#define JIM_DEBUG_COMMAND +#define JIM_DEBUG_PANIC +#endif + +const char *jim_tt_name(int type); + +#ifdef JIM_DEBUG_PANIC +static void JimPanicDump(int panic_condition, const char *fmt, ...); +#define JimPanic(X) JimPanicDump X +#else +#define JimPanic(X) +#endif + +/* ----------------------------------------------------------------------------- + * Global variables + * ---------------------------------------------------------------------------*/ + +/* A shared empty string for the objects string representation. + * Jim_InvalidateStringRep knows about it and doesn't try to free it. */ +static char JimEmptyStringRep[] = ""; + +/* ----------------------------------------------------------------------------- + * Required prototypes of not exported functions + * ---------------------------------------------------------------------------*/ +static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf); +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags); +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, + int flags); +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name); +static void JimDeleteLocalProcs(Jim_Interp *interp); +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, + int argc, Jim_Obj *const *argv); +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, + Jim_Obj *fileNameObj, int linenr); +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); +static int JimSign(jim_wide w); +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len); + + +static const Jim_HashTableType JimVariablesHashTableType; + +/* Fast access to the int (wide) value of an object which is known to be of int type */ +#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue + +#define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none") + +static int utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + +/* These can be used in addition to JIM_CASESENS/JIM_NOCASE */ +#define JIM_CHARSET_SCAN 2 +#define JIM_CHARSET_GLOB 0 + +/** + * pattern points to a string like "[^a-z\ub5]" + * + * The pattern may contain trailing chars, which are ignored. + * + * The pattern is matched against unicode char 'c'. + * + * If (flags & JIM_NOCASE), case is ignored when matching. + * If (flags & JIM_CHARSET_SCAN), the considers ^ and ] special at the start + * of the charset, per scan, rather than glob/string match. + * + * If the unicode char 'c' matches that set, returns a pointer to the ']' character, + * or the null character if the ']' is missing. + * + * Returns NULL on no match. + */ +static const char *JimCharsetMatch(const char *pattern, int c, int flags) +{ + int not = 0; + int pchar; + int match = 0; + int nocase = 0; + + if (flags & JIM_NOCASE) { + nocase++; + c = utf8_upper(c); + } + + if (flags & JIM_CHARSET_SCAN) { + if (*pattern == '^') { + not++; + pattern++; + } + + /* Special case. If the first char is ']', it is part of the set */ + if (*pattern == ']') { + goto first; + } + } + + while (*pattern && *pattern != ']') { + /* Exact match */ + if (pattern[0] == '\\') { +first: + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + } + else { + /* Is this a range? a-z */ + int start; + int end; + + pattern += utf8_tounicode_case(pattern, &start, nocase); + if (pattern[0] == '-' && pattern[1]) { + /* skip '-' */ + pattern += utf8_tounicode(pattern, &pchar); + pattern += utf8_tounicode_case(pattern, &end, nocase); + + /* Handle reversed range too */ + if ((c >= start && c <= end) || (c >= end && c <= start)) { + match = 1; + } + continue; + } + pchar = start; + } + + if (pchar == c) { + match = 1; + } + } + if (not) { + match = !match; + } + + return match ? pattern : NULL; +} + +/* Glob-style pattern matching. */ + +/* Note: string *must* be valid UTF-8 sequences + * slen is a char length, not byte counts. + */ +static int GlobMatch(const char *pattern, const char *string, int nocase) +{ + int c; + int pchar; + while (*pattern) { + switch (pattern[0]) { + case '*': + while (pattern[1] == '*') { + pattern++; + } + pattern++; + if (!pattern[0]) { + return 1; /* match */ + } + while (*string) { + /* Recursive call - Does the remaining pattern match anywhere? */ + if (GlobMatch(pattern, string, nocase)) + return 1; /* match */ + string += utf8_tounicode(string, &c); + } + return 0; /* no match */ + + case '?': + string += utf8_tounicode(string, &c); + break; + + case '[': { + string += utf8_tounicode(string, &c); + pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); + if (!pattern) { + return 0; + } + if (!*pattern) { + /* Ran out of pattern (no ']') */ + continue; + } + break; + } + case '\\': + if (pattern[1]) { + pattern++; + } + /* fall through */ + default: + string += utf8_tounicode_case(string, &c, nocase); + utf8_tounicode_case(pattern, &pchar, nocase); + if (pchar != c) { + return 0; + } + break; + } + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + if (!*string) { + while (*pattern == '*') { + pattern++; + } + break; + } + } + if (!*pattern && !*string) { + return 1; + } + return 0; +} + +static int JimStringMatch(Jim_Interp *interp, Jim_Obj *patternObj, const char *string, int nocase) +{ + return GlobMatch(Jim_String(patternObj), string, nocase); +} + +/** + * string comparison works on binary data. + * + * Note that the lengths are byte lengths, not char lengths. + */ +static int JimStringCompare(const char *s1, int l1, const char *s2, int l2) +{ + if (l1 < l2) { + return memcmp(s1, s2, l1) <= 0 ? -1 : 1; + } + else if (l2 < l1) { + return memcmp(s1, s2, l2) >= 0 ? 1 : -1; + } + else { + return JimSign(memcmp(s1, s2, l1)); + } +} + +/** + * No-case version. + * + * If maxchars is -1, compares to end of string. + * Otherwise compares at most 'maxchars' characters. + */ +static int JimStringCompareNoCase(const char *s1, const char *s2, int maxchars) +{ + while (*s1 && *s2 && maxchars) { + int c1, c2; + s1 += utf8_tounicode_case(s1, &c1, 1); + s2 += utf8_tounicode_case(s2, &c2, 1); + if (c1 != c2) { + return JimSign(c1 - c2); + } + maxchars--; + } + if (!maxchars) { + return 0; + } + /* One string or both terminated */ + if (*s1) { + return 1; + } + if (*s2) { + return -1; + } + return 0; +} + +/* Search 's1' inside 's2', starting to search from char 'index' of 's2'. + * The index of the first occurrence of s1 in s2 is returned. + * If s1 is not found inside s2, -1 is returned. */ +static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx) +{ + int i; + int l1bytelen; + + if (!l1 || !l2 || l1 > l2) { + return -1; + } + if (idx < 0) + idx = 0; + s2 += utf8_index(s2, idx); + + l1bytelen = utf8_index(s1, l1); + + for (i = idx; i <= l2 - l1; i++) { + int c; + if (memcmp(s2, s1, l1bytelen) == 0) { + return i; + } + s2 += utf8_tounicode(s2, &c); + } + return -1; +} + +/** + * Note: Lengths and return value are in bytes, not chars. + */ +static int JimStringLast(const char *s1, int l1, const char *s2, int l2) +{ + const char *p; + + if (!l1 || !l2 || l1 > l2) + return -1; + + /* Now search for the needle */ + for (p = s2 + l2 - 1; p != s2 - 1; p--) { + if (*p == *s1 && memcmp(s1, p, l1) == 0) { + return p - s2; + } + } + return -1; +} + +#ifdef JIM_UTF8 +/** + * Note: Lengths and return value are in chars. + */ +static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2) +{ + int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2)); + if (n > 0) { + n = utf8_strlen(s2, n); + } + return n; +} +#endif + +int Jim_WideToString(char *buf, jim_wide wideValue) +{ + const char *fmt = "%" JIM_WIDE_MODIFIER; + + return sprintf(buf, fmt, wideValue); +} + +/** + * After an strtol()/strtod()-like conversion, + * check whether something was converted and that + * the only thing left is white space. + * + * Returns JIM_OK or JIM_ERR. + */ +static int JimCheckConversion(const char *str, const char *endptr) +{ + if (str[0] == '\0' || str == endptr) { + return JIM_ERR; + } + + if (endptr[0] != '\0') { + while (*endptr) { + if (!isspace(UCHAR(*endptr))) { + return JIM_ERR; + } + endptr++; + } + } + return JIM_OK; +} + +int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) +{ + char *endptr; + + *widePtr = strtoull(str, &endptr, base); + + return JimCheckConversion(str, endptr); +} + +int Jim_DoubleToString(char *buf, double doubleValue) +{ + int len; + char *buf0 = buf; + + len = sprintf(buf, "%.12g", doubleValue); + + /* Add a final ".0" if it's a number. But not + * for NaN or InF */ + while (*buf) { + if (*buf == '.' || isalpha(UCHAR(*buf))) { + /* inf -> Inf, nan -> Nan */ + if (*buf == 'i' || *buf == 'n') { + *buf = toupper(UCHAR(*buf)); + } + if (*buf == 'I') { + /* Infinity -> Inf */ + buf[3] = '\0'; + len = buf - buf0 + 3; + } + return len; + } + buf++; + } + + *buf++ = '.'; + *buf++ = '0'; + *buf = '\0'; + + return len + 2; +} + +int Jim_StringToDouble(const char *str, double *doublePtr) +{ + char *endptr; + + /* Callers can check for underflow via ERANGE */ + errno = 0; + + *doublePtr = strtod(str, &endptr); + + return JimCheckConversion(str, endptr); +} + +static jim_wide JimPowWide(jim_wide b, jim_wide e) +{ + jim_wide i, res = 1; + + if ((b == 0 && e != 0) || (e < 0)) + return 0; + for (i = 0; i < e; i++) { + res *= b; + } + return res; +} + +/* ----------------------------------------------------------------------------- + * Special functions + * ---------------------------------------------------------------------------*/ +#ifdef JIM_DEBUG_PANIC +void JimPanicDump(int condition, const char *fmt, ...) +{ + va_list ap; + + if (!condition) { + return; + } + + va_start(ap, fmt); + + fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, JIM_NL JIM_NL); + va_end(ap); + +#ifdef HAVE_BACKTRACE + { + void *array[40]; + int size, i; + char **strings; + + size = backtrace(array, 40); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + fprintf(stderr, "[backtrace] %s" JIM_NL, strings[i]); + fprintf(stderr, "[backtrace] Include the above lines and the output" JIM_NL); + fprintf(stderr, "[backtrace] of 'nm <executable>' in the bug report." JIM_NL); + } +#endif + + abort(); +} +#endif + +/* ----------------------------------------------------------------------------- + * Memory allocation + * ---------------------------------------------------------------------------*/ + +void *Jim_Alloc(int size) +{ + return malloc(size); +} + +void Jim_Free(void *ptr) +{ + free(ptr); +} + +void *Jim_Realloc(void *ptr, int size) +{ + return realloc(ptr, size); +} + +char *Jim_StrDup(const char *s) +{ + return strdup(s); +} + +char *Jim_StrDupLen(const char *s, int l) +{ + char *copy = Jim_Alloc(l + 1); + + memcpy(copy, s, l + 1); + copy[l] = 0; /* Just to be sure, original could be substring */ + return copy; +} + +/* ----------------------------------------------------------------------------- + * Time related functions + * ---------------------------------------------------------------------------*/ + +/* Returns microseconds of CPU used since start. */ +static jim_wide JimClock(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec; +} + +/* ----------------------------------------------------------------------------- + * Hash Tables + * ---------------------------------------------------------------------------*/ + +/* -------------------------- private prototypes ---------------------------- */ +static int JimExpandHashTableIfNeeded(Jim_HashTable *ht); +static unsigned int JimHashTableNextPower(unsigned int size); +static int JimInsertHashEntry(Jim_HashTable *ht, const void *key); + +/* -------------------------- hash functions -------------------------------- */ + +/* Thomas Wang's 32 bit Mix Function */ +unsigned int Jim_IntHashFunction(unsigned int key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} + +/* Generic hash function (we are using to multiply by 9 and add the byte + * as Tcl) */ +unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) +{ + unsigned int h = 0; + + while (len--) + h += (h << 3) + *buf++; + return h; +} + +/* ----------------------------- API implementation ------------------------- */ + +/* reset a hashtable already initialized with ht_init(). + * NOTE: This function should only called by ht_destroy(). */ +static void JimResetHashTable(Jim_HashTable *ht) +{ + ht->table = NULL; + ht->size = 0; + ht->sizemask = 0; + ht->used = 0; + ht->collisions = 0; +} + +/* Initialize the hash table */ +int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) +{ + JimResetHashTable(ht); + ht->type = type; + ht->privdata = privDataPtr; + return JIM_OK; +} + +/* Resize the table to the minimal size that contains all the elements, + * but with the invariant of a USER/BUCKETS ration near to <= 1 */ +int Jim_ResizeHashTable(Jim_HashTable *ht) +{ + int minimal = ht->used; + + if (minimal < JIM_HT_INITIAL_SIZE) + minimal = JIM_HT_INITIAL_SIZE; + return Jim_ExpandHashTable(ht, minimal); +} + +/* Expand or create the hashtable */ +int Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) +{ + Jim_HashTable n; /* the new hashtable */ + unsigned int realsize = JimHashTableNextPower(size), i; + + /* the size is invalid if it is smaller than the number of + * elements already inside the hashtable */ + if (ht->used >= size) + return JIM_ERR; + + Jim_InitHashTable(&n, ht->type, ht->privdata); + n.size = realsize; + n.sizemask = realsize - 1; + n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); + + /* Initialize all the pointers to NULL */ + memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); + + /* Copy all the elements from the old to the new table: + * note that if the old hash table is empty ht->used is zero, + * so Jim_ExpandHashTable just creates an empty hash table. */ + n.used = ht->used; + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if (ht->table[i] == NULL) + continue; + + /* For each hash entry on this slot... */ + he = ht->table[i]; + while (he) { + unsigned int h; + + nextHe = he->next; + /* Get the new element index */ + h = Jim_HashKey(ht, he->key) & n.sizemask; + he->next = n.table[h]; + n.table[h] = he; + ht->used--; + /* Pass to the next element */ + he = nextHe; + } + } + assert(ht->used == 0); + Jim_Free(ht->table); + + /* Remap the new hashtable in the old */ + *ht = n; + return JIM_OK; +} + +/* Add an element to the target hash table */ +int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + int idx; + Jim_HashEntry *entry; + + /* Get the index of the new element, or -1 if + * the element already exists. */ + if ((idx = JimInsertHashEntry(ht, key)) == -1) + return JIM_ERR; + + /* Allocates the memory and stores key */ + entry = Jim_Alloc(sizeof(*entry)); + entry->next = ht->table[idx]; + ht->table[idx] = entry; + + /* Set the hash entry fields. */ + Jim_SetHashKey(ht, entry, key); + Jim_SetHashVal(ht, entry, val); + ht->used++; + return JIM_OK; +} + +/* Add an element, discarding the old if the key already exists */ +int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + Jim_HashEntry *entry; + + /* Try to add the element. If the key + * does not exists Jim_AddHashEntry will suceed. */ + if (Jim_AddHashEntry(ht, key, val) == JIM_OK) + return JIM_OK; + /* It already exists, get the entry */ + entry = Jim_FindHashEntry(ht, key); + /* Free the old value and set the new one */ + Jim_FreeEntryVal(ht, entry); + Jim_SetHashVal(ht, entry, val); + return JIM_OK; +} + +/* Search and remove an element */ +int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key) +{ + unsigned int h; + Jim_HashEntry *he, *prevHe; + + if (ht->used == 0) + return JIM_ERR; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + + prevHe = NULL; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) { + /* Unlink the element from the list */ + if (prevHe) + prevHe->next = he->next; + else + ht->table[h] = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + return JIM_OK; + } + prevHe = he; + he = he->next; + } + return JIM_ERR; /* not found */ +} + +/* Destroy an entire hash table */ +int Jim_FreeHashTable(Jim_HashTable *ht) +{ + unsigned int i; + + /* Free all the elements */ + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if ((he = ht->table[i]) == NULL) + continue; + while (he) { + nextHe = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + he = nextHe; + } + } + /* Free the table and the allocated cache structure */ + Jim_Free(ht->table); + /* Re-initialize the table */ + JimResetHashTable(ht); + return JIM_OK; /* never fails */ +} + +Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) +{ + Jim_HashEntry *he; + unsigned int h; + + if (ht->used == 0) + return NULL; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return he; + he = he->next; + } + return NULL; +} + +Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) +{ + Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); + + iter->ht = ht; + iter->index = -1; + iter->entry = NULL; + iter->nextEntry = NULL; + return iter; +} + +Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) +{ + while (1) { + if (iter->entry == NULL) { + iter->index++; + if (iter->index >= (signed)iter->ht->size) + break; + iter->entry = iter->ht->table[iter->index]; + } + else { + iter->entry = iter->nextEntry; + } + if (iter->entry) { + /* We need to save the 'next' here, the iterator user + * may delete the entry we are returning. */ + iter->nextEntry = iter->entry->next; + return iter->entry; + } + } + return NULL; +} + +/* ------------------------- private functions ------------------------------ */ + +/* Expand the hash table if needed */ +static int JimExpandHashTableIfNeeded(Jim_HashTable *ht) +{ + /* If the hash table is empty expand it to the intial size, + * if the table is "full" dobule its size. */ + if (ht->size == 0) + return Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE); + if (ht->size == ht->used) + return Jim_ExpandHashTable(ht, ht->size * 2); + return JIM_OK; +} + +/* Our hash table capability is a power of two */ +static unsigned int JimHashTableNextPower(unsigned int size) +{ + unsigned int i = JIM_HT_INITIAL_SIZE; + + if (size >= 2147483648U) + return 2147483648U; + while (1) { + if (i >= size) + return i; + i *= 2; + } +} + +/* Returns the index of a free slot that can be populated with + * an hash entry for the given 'key'. + * If the key already exists, -1 is returned. */ +static int JimInsertHashEntry(Jim_HashTable *ht, const void *key) +{ + unsigned int h; + Jim_HashEntry *he; + + /* Expand the hashtable if needed */ + if (JimExpandHashTableIfNeeded(ht) == JIM_ERR) + return -1; + /* Compute the key hash value */ + h = Jim_HashKey(ht, key) & ht->sizemask; + /* Search if this slot does not already contain the given key */ + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return -1; + he = he->next; + } + return h; +} + +/* ----------------------- StringCopy Hash Table Type ------------------------*/ + +static unsigned int JimStringCopyHTHashFunction(const void *key) +{ + return Jim_GenHashFunction(key, strlen(key)); +} + +static const void *JimStringCopyHTKeyDup(void *privdata, const void *key) +{ + int len = strlen(key); + char *copy = Jim_Alloc(len + 1); + + JIM_NOTUSED(privdata); + + memcpy(copy, key, len); + copy[len] = '\0'; + return copy; +} + +static void *JimStringKeyValCopyHTValDup(void *privdata, const void *val) +{ + int len = strlen(val); + char *copy = Jim_Alloc(len + 1); + + JIM_NOTUSED(privdata); + + memcpy(copy, val, len); + copy[len] = '\0'; + return copy; +} + +static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return strcmp(key1, key2) == 0; +} + +static void JimStringCopyHTKeyDestructor(void *privdata, const void *key) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)key); /* ATTENTION: const cast */ +} + +static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)val); /* ATTENTION: const cast */ +} + +#if 0 +static Jim_HashTableType JimStringCopyHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; +#endif + +/* This is like StringCopy but does not auto-duplicate the key. + * It's used for intepreter's shared strings. */ +static const Jim_HashTableType JimSharedStringsHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + NULL, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; + +/* This is like StringCopy but also automatically handle dynamic + * allocated C strings as values. */ +static const Jim_HashTableType JimStringKeyValCopyHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + JimStringKeyValCopyHTValDup, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimStringKeyValCopyHTValDestructor, /* val destructor */ +}; + +typedef struct AssocDataValue +{ + Jim_InterpDeleteProc *delProc; + void *data; +} AssocDataValue; + +static void JimAssocDataHashTableValueDestructor(void *privdata, void *data) +{ + AssocDataValue *assocPtr = (AssocDataValue *) data; + + if (assocPtr->delProc != NULL) + assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); + Jim_Free(data); +} + +static const Jim_HashTableType JimAssocDataHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimAssocDataHashTableValueDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Stack - This is a simple generic stack implementation. It is used for + * example in the 'expr' expression compiler. + * ---------------------------------------------------------------------------*/ +void Jim_InitStack(Jim_Stack *stack) +{ + stack->len = 0; + stack->maxlen = 0; + stack->vector = NULL; +} + +void Jim_FreeStack(Jim_Stack *stack) +{ + Jim_Free(stack->vector); +} + +int Jim_StackLen(Jim_Stack *stack) +{ + return stack->len; +} + +void Jim_StackPush(Jim_Stack *stack, void *element) +{ + int neededLen = stack->len + 1; + + if (neededLen > stack->maxlen) { + stack->maxlen = neededLen < 20 ? 20 : neededLen * 2; + stack->vector = Jim_Realloc(stack->vector, sizeof(void *) * stack->maxlen); + } + stack->vector[stack->len] = element; + stack->len++; +} + +void *Jim_StackPop(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + stack->len--; + return stack->vector[stack->len]; +} + +void *Jim_StackPeek(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + return stack->vector[stack->len - 1]; +} + +void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr)) +{ + int i; + + for (i = 0; i < stack->len; i++) + freeFunc(stack->vector[i]); +} + +/* ----------------------------------------------------------------------------- + * Parser + * ---------------------------------------------------------------------------*/ + +/* Token types */ +#define JIM_TT_NONE 0 /* No token returned */ +#define JIM_TT_STR 1 /* simple string */ +#define JIM_TT_ESC 2 /* string that needs escape chars conversion */ +#define JIM_TT_VAR 3 /* var substitution */ +#define JIM_TT_DICTSUGAR 4 /* Syntax sugar for [dict get], $foo(bar) */ +#define JIM_TT_CMD 5 /* command substitution */ +/* Note: Keep these three together for TOKEN_IS_SEP() */ +#define JIM_TT_SEP 6 /* word separator. arg is # of tokens. -ve if {*} */ +#define JIM_TT_EOL 7 /* line separator */ +#define JIM_TT_EOF 8 /* end of script */ + +#define JIM_TT_LINE 9 /* special 'start-of-line' token. arg is # of arguments to the command. -ve if {*} */ +#define JIM_TT_WORD 10 /* special 'start-of-word' token. arg is # of tokens to combine. -ve if {*} */ + +/* Additional token types needed for expressions */ +#define JIM_TT_SUBEXPR_START 11 +#define JIM_TT_SUBEXPR_END 12 +#define JIM_TT_SUBEXPR_COMMA 13 +#define JIM_TT_EXPR_INT 14 +#define JIM_TT_EXPR_DOUBLE 15 + +#define JIM_TT_EXPRSUGAR 16 /* $(expression) */ + +/* Operator token types start here */ +#define JIM_TT_EXPR_OP 20 + +#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) + +/* Parser states */ +#define JIM_PS_DEF 0 /* Default state */ +#define JIM_PS_QUOTE 1 /* Inside "" */ +#define JIM_PS_DICTSUGAR 2 /* Tokenising abc(def) into 4 separate tokens */ + +/* Parser context structure. The same context is used both to parse + * Tcl scripts and lists. */ +struct JimParserCtx +{ + const char *p; /* Pointer to the point of the program we are parsing */ + int len; /* Remaining length */ + int linenr; /* Current line number */ + const char *tstart; + const char *tend; /* Returned token is at tstart-tend in 'prg'. */ + int tline; /* Line number of the returned token */ + int tt; /* Token type */ + int eof; /* Non zero if EOF condition is true. */ + int state; /* Parser state */ + int comment; /* Non zero if the next chars may be a comment. */ + char missing; /* At end of parse, ' ' if complete, '{' if braces incomplete, '"' if quotes incomplete */ + int missingline; /* Line number starting the missing token */ +}; + +/** + * Results of missing quotes, braces, etc. from parsing. + */ +struct JimParseResult { + char missing; /* From JimParserCtx.missing */ + int line; /* From JimParserCtx.missingline */ +}; + +static int JimParseScript(struct JimParserCtx *pc); +static int JimParseSep(struct JimParserCtx *pc); +static int JimParseEol(struct JimParserCtx *pc); +static int JimParseCmd(struct JimParserCtx *pc); +static int JimParseQuote(struct JimParserCtx *pc); +static int JimParseVar(struct JimParserCtx *pc); +static int JimParseBrace(struct JimParserCtx *pc); +static int JimParseStr(struct JimParserCtx *pc); +static int JimParseComment(struct JimParserCtx *pc); +static void JimParseSubCmd(struct JimParserCtx *pc); +static int JimParseSubQuote(struct JimParserCtx *pc); +static void JimParseSubCmd(struct JimParserCtx *pc); +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); + +/* Initialize a parser context. + * 'prg' is a pointer to the program text, linenr is the line + * number of the first line contained in the program. */ +static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) +{ + pc->p = prg; + pc->len = len; + pc->tstart = NULL; + pc->tend = NULL; + pc->tline = 0; + pc->tt = JIM_TT_NONE; + pc->eof = 0; + pc->state = JIM_PS_DEF; + pc->linenr = linenr; + pc->comment = 1; + pc->missing = ' '; + pc->missingline = linenr; +} + +static int JimParseScript(struct JimParserCtx *pc) +{ + while (1) { /* the while is used to reiterate with continue if needed */ + if (!pc->len) { + pc->tstart = pc->p; + pc->tend = pc->p - 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '\\': + if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) { + return JimParseSep(pc); + } + else { + pc->comment = 0; + return JimParseStr(pc); + } + break; + case ' ': + case '\t': + case '\r': + if (pc->state == JIM_PS_DEF) + return JimParseSep(pc); + else { + pc->comment = 0; + return JimParseStr(pc); + } + break; + case '\n': + case ';': + pc->comment = 1; + if (pc->state == JIM_PS_DEF) + return JimParseEol(pc); + else + return JimParseStr(pc); + break; + case '[': + pc->comment = 0; + return JimParseCmd(pc); + break; + case '$': + pc->comment = 0; + if (JimParseVar(pc) == JIM_ERR) { + pc->tstart = pc->tend = pc->p++; + pc->len--; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + return JIM_OK; + } + else + return JIM_OK; + break; + case '#': + if (pc->comment) { + JimParseComment(pc); + continue; + } + else { + return JimParseStr(pc); + } + default: + pc->comment = 0; + return JimParseStr(pc); + break; + } + return JIM_OK; + } +} + +static int JimParseSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || + (*pc->p == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\\') { + pc->p++; + pc->len--; + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseEol(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\n' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == ';') { + if (*pc->p == '\n') + pc->linenr++; + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_EOL; + return JIM_OK; +} + +/* +** Here are the rules for parsing: +** {braced expression} +** - Count open and closing braces +** - Backslash escapes meaning of braces +** +** "quoted expression" +** - First double quote at start of word terminates the expression +** - Backslash escapes quote and bracket +** - [commands brackets] are counted/nested +** - command rules apply within [brackets], not quoting rules (i.e. quotes have their own rules) +** +** [command expression] +** - Count open and closing brackets +** - Backslash escapes quote, bracket and brace +** - [commands brackets] are counted/nested +** - "quoted expressions" are parsed according to quoting rules +** - {braced expressions} are parsed according to brace rules +** +** For everything, backslash escapes the next char, newline increments current line +*/ + +/** + * Parses a braced expression starting at pc->p. + * + * Positions the parser at the end of the braced expression, + * sets pc->tend and possibly pc->missing. + */ +static void JimParseSubBrace(struct JimParserCtx *pc) +{ + int level = 1; + + /* Skip the brace */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '{': + level++; + break; + + case '}': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '\n': + pc->linenr++; + break; + } + pc->p++; + pc->len--; + } + pc->missing = '{'; + pc->missingline = pc->tline; + pc->tend = pc->p - 1; +} + +/** + * Parses a quoted expression starting at pc->p. + * + * Positions the parser at the end of the quoted expression, + * sets pc->tend and possibly pc->missing. + * + * Returns the type of the token of the string, + * either JIM_TT_ESC (if it contains values which need to be [subst]ed) + * or JIM_TT_STR. + */ +static int JimParseSubQuote(struct JimParserCtx *pc) +{ + int tt = JIM_TT_STR; + int line = pc->tline; + + /* Skip the quote */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + tt = JIM_TT_ESC; + } + break; + + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return tt; + + case '[': + JimParseSubCmd(pc); + tt = JIM_TT_ESC; + continue; + + case '\n': + pc->linenr++; + break; + + case '$': + tt = JIM_TT_ESC; + break; + } + pc->p++; + pc->len--; + } + pc->missing = '"'; + pc->missingline = line; + pc->tend = pc->p - 1; + return tt; +} + +/** + * Parses a [command] expression starting at pc->p. + * + * Positions the parser at the end of the command expression, + * sets pc->tend and possibly pc->missing. + */ +static void JimParseSubCmd(struct JimParserCtx *pc) +{ + int level = 1; + int startofword = 1; + int line = pc->tline; + + /* Skip the bracket */ + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '[': + level++; + break; + + case ']': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '"': + if (startofword) { + JimParseSubQuote(pc); + continue; + } + break; + + case '{': + JimParseSubBrace(pc); + startofword = 0; + continue; + + case '\n': + pc->linenr++; + break; + } + startofword = isspace(UCHAR(*pc->p)); + pc->p++; + pc->len--; + } + pc->missing = '['; + pc->missingline = line; + pc->tend = pc->p - 1; +} + +static int JimParseBrace(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + JimParseSubBrace(pc); + return JIM_OK; +} + +static int JimParseCmd(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_CMD; + JimParseSubCmd(pc); + return JIM_OK; +} + +static int JimParseQuote(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JimParseSubQuote(pc); + return JIM_OK; +} + +static int JimParseVar(struct JimParserCtx *pc) +{ + /* skip the $ */ + pc->p++; + pc->len--; + +#ifdef EXPRSUGAR_BRACKET + if (*pc->p == '[') { + /* Parse $[...] expr shorthand syntax */ + JimParseCmd(pc); + pc->tt = JIM_TT_EXPRSUGAR; + return JIM_OK; + } +#endif + + pc->tstart = pc->p; + pc->tt = JIM_TT_VAR; + pc->tline = pc->linenr; + + if (*pc->p == '{') { + pc->tstart = ++pc->p; + pc->len--; + + while (pc->len && *pc->p != '}') { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + if (pc->len) { + pc->p++; + pc->len--; + } + } + else { + while (1) { + /* Skip double colon, but not single colon! */ + if (pc->p[0] == ':' && pc->p[1] == ':') { + pc->p += 2; + pc->len -= 2; + continue; + } + if (isalnum(UCHAR(*pc->p)) || *pc->p == '_') { + pc->p++; + pc->len--; + continue; + } + break; + } + /* Parse [dict get] syntax sugar. */ + if (*pc->p == '(') { + int count = 1; + const char *paren = NULL; + + pc->tt = JIM_TT_DICTSUGAR; + + while (count && pc->len) { + pc->p++; + pc->len--; + if (*pc->p == '\\' && pc->len >= 1) { + pc->p++; + pc->len--; + } + else if (*pc->p == '(') { + count++; + } + else if (*pc->p == ')') { + paren = pc->p; + count--; + } + } + if (count == 0) { + pc->p++; + pc->len--; + } + else if (paren) { + /* Did not find a matching paren. Back up */ + paren++; + pc->len += (pc->p - paren); + pc->p = paren; + } +#ifndef EXPRSUGAR_BRACKET + if (*pc->tstart == '(') { + pc->tt = JIM_TT_EXPRSUGAR; + } +#endif + } + pc->tend = pc->p - 1; + } + /* Check if we parsed just the '$' character. + * That's not a variable so an error is returned + * to tell the state machine to consider this '$' just + * a string. */ + if (pc->tstart == pc->p) { + pc->p--; + pc->len++; + return JIM_ERR; + } + return JIM_OK; +} + +static int JimParseStr(struct JimParserCtx *pc) +{ + int newword = (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || + pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR); + if (newword && *pc->p == '{') { + return JimParseBrace(pc); + } + else if (newword && *pc->p == '"') { + pc->state = JIM_PS_QUOTE; + pc->p++; + pc->len--; + /* In case the end quote is missing */ + pc->missingline = pc->tline; + } + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (1) { + if (pc->len == 0) { + if (pc->state == JIM_PS_QUOTE) { + pc->missing = '"'; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + switch (*pc->p) { + case '\\': + if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + if (pc->len >= 2) { + if (*(pc->p + 1) == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + break; + case '(': + /* If the following token is not '$' just keep going */ + if (pc->len > 1 && pc->p[1] != '$') { + break; + } + case ')': + /* Only need a separate ')' token if the previous was a var */ + if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { + if (pc->p == pc->tstart) { + /* At the start of the token, so just return this char */ + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + break; + + case '$': + case '[': + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + case ' ': + case '\t': + case '\n': + case '\r': + case ';': + if (pc->state == JIM_PS_DEF) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + else if (*pc->p == '\n') { + pc->linenr++; + } + break; + case '"': + if (pc->state == JIM_PS_QUOTE) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + pc->p++; + pc->len--; + pc->state = JIM_PS_DEF; + return JIM_OK; + } + break; + } + pc->p++; + pc->len--; + } + return JIM_OK; /* unreached */ +} + +static int JimParseComment(struct JimParserCtx *pc) +{ + while (*pc->p) { + if (*pc->p == '\n') { + pc->linenr++; + if (*(pc->p - 1) != '\\') { + pc->p++; + pc->len--; + return JIM_OK; + } + } + pc->p++; + pc->len--; + } + return JIM_OK; +} + +/* xdigitval and odigitval are helper functions for JimEscape() */ +static int xdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int odigitval(int c) +{ + if (c >= '0' && c <= '7') + return c - '0'; + return -1; +} + +/* Perform Tcl escape substitution of 's', storing the result + * string into 'dest'. The escaped string is guaranteed to + * be the same length or shorted than the source string. + * Slen is the length of the string at 's', if it's -1 the string + * length will be calculated by the function. + * + * The function returns the length of the resulting string. */ +static int JimEscape(char *dest, const char *s, int slen) +{ + char *p = dest; + int i, len; + + if (slen == -1) + slen = strlen(s); + + for (i = 0; i < slen; i++) { + switch (s[i]) { + case '\\': + switch (s[i + 1]) { + case 'a': + *p++ = 0x7; + i++; + break; + case 'b': + *p++ = 0x8; + i++; + break; + case 'f': + *p++ = 0xc; + i++; + break; + case 'n': + *p++ = 0xa; + i++; + break; + case 'r': + *p++ = 0xd; + i++; + break; + case 't': + *p++ = 0x9; + i++; + break; + case 'u': + case 'x': + /* A unicode or hex sequence. + * \u Expect 1-4 hex chars and convert to utf-8. + * \x Expect 1-2 hex chars and convert to hex. + * An invalid sequence means simply the escaped char. + */ + { + int val = 0; + int k; + + i++; + + for (k = 0; k < (s[i] == 'u' ? 4 : 2); k++) { + int c = xdigitval(s[i + k + 1]); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + if (k) { + /* Got a valid sequence, so convert */ + if (s[i] == 'u') { + p += utf8_fromunicode(p, val); + } + else { + *p++ = val; + } + i += k; + break; + } + /* Not a valid codepoint, just an escaped char */ + *p++ = s[i]; + } + break; + case 'v': + *p++ = 0xb; + i++; + break; + case '\0': + *p++ = '\\'; + i++; + break; + case '\n': + /* Replace all spaces and tabs after backslash newline with a single space*/ + *p++ = ' '; + do { + i++; + } while (s[i + 1] == ' ' || s[i + 1] == '\t'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + /* octal escape */ + { + int val = 0; + int c = odigitval(s[i + 1]); + + val = c; + c = odigitval(s[i + 2]); + if (c == -1) { + *p++ = val; + i++; + break; + } + val = (val * 8) + c; + c = odigitval(s[i + 3]); + if (c == -1) { + *p++ = val; + i += 2; + break; + } + val = (val * 8) + c; + *p++ = val; + i += 3; + } + break; + default: + *p++ = s[i + 1]; + i++; + break; + } + break; + default: + *p++ = s[i]; + break; + } + } + len = p - dest; + *p = '\0'; + return len; +} + +/* Returns a dynamically allocated copy of the current token in the + * parser context. The function performs conversion of escapes if + * the token is of type JIM_TT_ESC. + * + * Note that after the conversion, tokens that are grouped with + * braces in the source code, are always recognizable from the + * identical string obtained in a different way from the type. + * + * For example the string: + * + * {*}$a + * + * will return as first token "*", of type JIM_TT_STR + * + * While the string: + * + * *$a + * + * will return as first token "*", of type JIM_TT_ESC + */ +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc) +{ + const char *start, *end; + char *token; + int len; + + start = pc->tstart; + end = pc->tend; + if (start > end) { + len = 0; + token = Jim_Alloc(1); + token[0] = '\0'; + } + else { + len = (end - start) + 1; + token = Jim_Alloc(len + 1); + if (pc->tt != JIM_TT_ESC) { + /* No escape conversion needed? Just copy it. */ + memcpy(token, start, len); + token[len] = '\0'; + } + else { + /* Else convert the escape chars. */ + len = JimEscape(token, start, len); + } + } + + return Jim_NewStringObjNoAlloc(interp, token, len); +} + +/* Parses the given string to determine if it represents a complete script. + * + * This is useful for interactive shells implementation, for [info complete]. + * + * If 'stateCharPtr' != NULL, the function stores ' ' on complete script, + * '{' on scripts incomplete missing one or more '}' to be balanced. + * '[' on scripts incomplete missing one or more ']' to be balanced. + * '"' on scripts incomplete missing a '"' char. + * + * If the script is complete, 1 is returned, otherwise 0. + */ +int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr) +{ + struct JimParserCtx parser; + + JimParserInit(&parser, s, len, 1); + while (!parser.eof) { + JimParseScript(&parser); + } + if (stateCharPtr) { + *stateCharPtr = parser.missing; + } + return parser.missing == ' '; +} + +/* ----------------------------------------------------------------------------- + * Tcl Lists parsing + * ---------------------------------------------------------------------------*/ +static int JimParseListSep(struct JimParserCtx *pc); +static int JimParseListStr(struct JimParserCtx *pc); +static int JimParseListQuote(struct JimParserCtx *pc); + +static int JimParseList(struct JimParserCtx *pc) +{ + switch (*pc->p) { + case ' ': + case '\n': + case '\t': + case '\r': + return JimParseListSep(pc); + + case '"': + return JimParseListQuote(pc); + + case '{': + return JimParseBrace(pc); + + default: + if (pc->len) { + return JimParseListStr(pc); + } + break; + } + + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; +} + +static int JimParseListSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (*pc->p == ' ' || *pc->p == '\t' || *pc->p == '\r' || *pc->p == '\n') { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseListQuote(struct JimParserCtx *pc) +{ + pc->p++; + pc->len--; + + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + switch (*pc->p) { + case '\\': + pc->tt = JIM_TT_ESC; + if (--pc->len == 0) { + /* Trailing backslash */ + pc->tend = pc->p; + return JIM_OK; + } + pc->p++; + break; + case '\n': + pc->linenr++; + break; + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return JIM_OK; + } + pc->p++; + pc->len--; + } + + pc->tend = pc->p - 1; + return JIM_OK; +} + +static int JimParseListStr(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + switch (*pc->p) { + case '\\': + if (--pc->len == 0) { + /* Trailing backslash */ + pc->tend = pc->p; + return JIM_OK; + } + pc->tt = JIM_TT_ESC; + pc->p++; + break; + case ' ': + case '\t': + case '\n': + case '\r': + pc->tend = pc->p - 1; + return JIM_OK; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Jim_Obj related functions + * ---------------------------------------------------------------------------*/ + +/* Return a new initialized object. */ +Jim_Obj *Jim_NewObj(Jim_Interp *interp) +{ + Jim_Obj *objPtr; + + /* -- Check if there are objects in the free list -- */ + if (interp->freeList != NULL) { + /* -- Unlink the object from the free list -- */ + objPtr = interp->freeList; + interp->freeList = objPtr->nextObjPtr; + } + else { + /* -- No ready to use objects: allocate a new one -- */ + objPtr = Jim_Alloc(sizeof(*objPtr)); + } + + /* Object is returned with refCount of 0. Every + * kind of GC implemented should take care to don't try + * to scan objects with refCount == 0. */ + objPtr->refCount = 0; + /* All the other fields are left not initialized to save time. + * The caller will probably want to set them to the right + * value anyway. */ + + /* -- Put the object into the live list -- */ + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->liveList; + if (interp->liveList) + interp->liveList->prevObjPtr = objPtr; + interp->liveList = objPtr; + + return objPtr; +} + +/* Free an object. Actually objects are never freed, but + * just moved to the free objects list, where they will be + * reused by Jim_NewObj(). */ +void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + /* Check if the object was already freed, panic. */ + JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, + objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>")); + + /* Free the internal representation */ + Jim_FreeIntRep(interp, objPtr); + /* Free the string representation */ + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + /* Unlink the object from the live objects list */ + if (objPtr->prevObjPtr) + objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; + if (objPtr->nextObjPtr) + objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; + if (interp->liveList == objPtr) + interp->liveList = objPtr->nextObjPtr; + /* Link the object into the free objects list */ + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->freeList; + if (interp->freeList) + interp->freeList->prevObjPtr = objPtr; + interp->freeList = objPtr; + objPtr->refCount = -1; +} + +/* Invalidate the string representation of an object. */ +void Jim_InvalidateStringRep(Jim_Obj *objPtr) +{ + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + objPtr->bytes = NULL; +} + +#define Jim_SetStringRep(o, b, l) \ + do { (o)->bytes = b; (o)->length = l; } while (0) + +/* Set the initial string representation for an object. + * Does not try to free an old one. */ +void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length) +{ + if (length == 0) { + objPtr->bytes = JimEmptyStringRep; + objPtr->length = 0; + } + else { + objPtr->bytes = Jim_Alloc(length + 1); + objPtr->length = length; + memcpy(objPtr->bytes, bytes, length); + objPtr->bytes[length] = '\0'; + } +} + +/* Duplicate an object. The returned object has refcount = 0. */ +Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *dupPtr; + + dupPtr = Jim_NewObj(interp); + if (objPtr->bytes == NULL) { + /* Object does not have a valid string representation. */ + dupPtr->bytes = NULL; + } + else { + Jim_InitStringRep(dupPtr, objPtr->bytes, objPtr->length); + } + + /* By default, the new object has the same type as the old object */ + dupPtr->typePtr = objPtr->typePtr; + if (objPtr->typePtr != NULL) { + if (objPtr->typePtr->dupIntRepProc == NULL) { + dupPtr->internalRep = objPtr->internalRep; + } + else { + /* The dup proc may set a different type, e.g. NULL */ + objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); + } + } + return dupPtr; +} + +/* Return the string representation for objPtr. If the object + * string representation is invalid, calls the method to create + * a new one starting from the internal representation of the object. */ +const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) +{ + if (objPtr->bytes == NULL) { + /* Invalid string repr. Generate it. */ + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + if (lenPtr) + *lenPtr = objPtr->length; + return objPtr->bytes; +} + +/* Just returns the length of the object's string rep */ +int Jim_Length(Jim_Obj *objPtr) +{ + int len; + + Jim_GetString(objPtr, &len); + return len; +} + +static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType dictSubstObjType = { + "dict-substitution", + FreeDictSubstInternalRep, + DupDictSubstInternalRep, + NULL, + JIM_TYPE_NONE, +}; + +static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, (Jim_Obj *)objPtr->internalRep.twoPtrValue.ptr2); +} + +static const Jim_ObjType interpolatedObjType = { + "interpolated", + FreeInterpolatedInternalRep, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +/* ----------------------------------------------------------------------------- + * String Object + * ---------------------------------------------------------------------------*/ +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType stringObjType = { + "string", + NULL, + DupStringInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + /* This is a bit subtle: the only caller of this function + * should be Jim_DuplicateObj(), that will copy the + * string representaion. After the copy, the duplicated + * object will not have more room in teh buffer than + * srcPtr->length bytes. So we just set it to length. */ + dupPtr->internalRep.strValue.maxLength = srcPtr->length; + + dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; +} + +static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + /* Get a fresh string representation. */ + (void)Jim_String(objPtr); + /* Free any other internal representation. */ + Jim_FreeIntRep(interp, objPtr); + /* Set it as string, i.e. just set the maxLength field. */ + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = objPtr->length; + /* Don't know the utf-8 length yet */ + objPtr->internalRep.strValue.charLength = -1; + return JIM_OK; +} + +/** + * Returns the length of the object string in chars, not bytes. + * + * These may be different for a utf-8 string. + */ +int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr) +{ +#ifdef JIM_UTF8 + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + + if (objPtr->internalRep.strValue.charLength < 0) { + objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length); + } + return objPtr->internalRep.strValue.charLength; +#else + return Jim_Length(objPtr); +#endif +} + +/* len is in bytes -- see also Jim_NewStringObjUtf8() */ +Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + /* Need to find out how many bytes the string requires */ + if (len == -1) + len = strlen(s); + /* Alloc/Set the string rep. */ + if (len == 0) { + objPtr->bytes = JimEmptyStringRep; + objPtr->length = 0; + } + else { + objPtr->bytes = Jim_Alloc(len + 1); + objPtr->length = len; + memcpy(objPtr->bytes, s, len); + objPtr->bytes[len] = '\0'; + } + + /* No typePtr field for the vanilla string object. */ + objPtr->typePtr = NULL; + return objPtr; +} + +/* charlen is in characters -- see also Jim_NewStringObj() */ +Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) +{ +#ifdef JIM_UTF8 + /* Need to find out how many bytes the string requires */ + int bytelen = utf8_index(s, charlen); + + Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); + + /* Remember the utf8 length, so set the type */ + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = bytelen; + objPtr->internalRep.strValue.charLength = charlen; + + return objPtr; +#else + return Jim_NewStringObj(interp, s, charlen); +#endif +} + +/* This version does not try to duplicate the 's' pointer, but + * use it directly. */ +Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + if (len == -1) + len = strlen(s); + Jim_SetStringRep(objPtr, s, len); + objPtr->typePtr = NULL; + return objPtr; +} + +/* Low-level string append. Use it only against objects + * of type "string". */ +static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) +{ + int needlen; + + if (len == -1) + len = strlen(str); + needlen = objPtr->length + len; + if (objPtr->internalRep.strValue.maxLength < needlen || + objPtr->internalRep.strValue.maxLength == 0) { + needlen *= 2; + /* Inefficient to malloc() for less than 8 bytes */ + if (needlen < 7) { + needlen = 7; + } + if (objPtr->bytes == JimEmptyStringRep) { + objPtr->bytes = Jim_Alloc(needlen + 1); + } + else { + objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1); + } + objPtr->internalRep.strValue.maxLength = needlen; + } + memcpy(objPtr->bytes + objPtr->length, str, len); + objPtr->bytes[objPtr->length + len] = '\0'; + if (objPtr->internalRep.strValue.charLength >= 0) { + /* Update the utf-8 char length */ + objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); + } + objPtr->length += len; +} + +/* Higher level API to append strings to objects. */ +void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) +{ + JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + StringAppendString(objPtr, str, len); +} + +void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) +{ + int len; + const char *str; + + str = Jim_GetString(appendObjPtr, &len); + Jim_AppendString(interp, objPtr, str, len); +} + +void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) +{ + va_list ap; + + if (objPtr->typePtr != &stringObjType) + SetStringFromAny(interp, objPtr); + va_start(ap, objPtr); + while (1) { + char *s = va_arg(ap, char *); + + if (s == NULL) + break; + Jim_AppendString(interp, objPtr, s, -1); + } + va_end(ap); +} + +int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) +{ + const char *aStr, *bStr; + int aLen, bLen; + + if (aObjPtr == bObjPtr) + return 1; + aStr = Jim_GetString(aObjPtr, &aLen); + bStr = Jim_GetString(bObjPtr, &bLen); + if (aLen != bLen) + return 0; + return JimStringCompare(aStr, aLen, bStr, bLen) == 0; +} + +int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) +{ + return JimStringMatch(interp, patternObjPtr, Jim_String(objPtr), nocase); +} + +int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) +{ + const char *s1, *s2; + int l1, l2; + + s1 = Jim_GetString(firstObjPtr, &l1); + s2 = Jim_GetString(secondObjPtr, &l2); + + if (nocase) { + return JimStringCompareNoCase(s1, s2, -1); + } + return JimStringCompare(s1, l1, s2, l2); +} + +/* Convert a range, as returned by Jim_GetRange(), into + * an absolute index into an object of the specified length. + * This function may return negative values, or values + * bigger or equal to the length of the list if the index + * is out of range. */ +static int JimRelToAbsIndex(int len, int idx) +{ + if (idx < 0) + return len + idx; + return idx; +} + +/* Convert a pair of index as normalize by JimRelToAbsIndex(), + * into a range stored in *firstPtr, *lastPtr, *rangeLenPtr, suitable + * for implementation of commands like [string range] and [lrange]. + * + * The resulting range is guaranteed to address valid elements of + * the structure. */ +static void JimRelToAbsRange(int len, int first, int last, + int *firstPtr, int *lastPtr, int *rangeLenPtr) +{ + int rangeLen; + + if (first > last) { + rangeLen = 0; + } + else { + rangeLen = last - first + 1; + if (rangeLen) { + if (first < 0) { + rangeLen += first; + first = 0; + } + if (last >= len) { + rangeLen -= (last - (len - 1)); + last = len - 1; + } + } + } + if (rangeLen < 0) + rangeLen = 0; + + *firstPtr = first; + *lastPtr = last; + *rangeLenPtr = rangeLen; +} + +Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ + int first, last; + const char *str; + int rangeLen; + int bytelen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + str = Jim_GetString(strObjPtr, &bytelen); + first = JimRelToAbsIndex(bytelen, first); + last = JimRelToAbsIndex(bytelen, last); + JimRelToAbsRange(bytelen, first, last, &first, &last, &rangeLen); + if (first == 0 && rangeLen == bytelen) { + return strObjPtr; + } + return Jim_NewStringObj(interp, str + first, rangeLen); +} + +Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ +#ifdef JIM_UTF8 + int first, last; + const char *str; + int len, rangeLen; + int bytelen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + str = Jim_GetString(strObjPtr, &bytelen); + len = Jim_Utf8Length(interp, strObjPtr); + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + if (first == 0 && rangeLen == len) { + return strObjPtr; + } + if (len == bytelen) { + /* ASCII optimisation */ + return Jim_NewStringObj(interp, str + first, rangeLen); + } + return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); +#else + return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); +#endif +} + +static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf, *p; + int len; + const char *str; + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + str = Jim_GetString(strObjPtr, &len); + + buf = p = Jim_Alloc(len + 1); + while (*str) { + int c; + str += utf8_tounicode(str, &c); + p += utf8_fromunicode(p, utf8_lower(c)); + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buf, len); +} + +static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf, *p; + int len; + const char *str; + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + str = Jim_GetString(strObjPtr, &len); + + buf = p = Jim_Alloc(len + 1); + while (*str) { + int c; + str += utf8_tounicode(str, &c); + p += utf8_fromunicode(p, utf8_upper(c)); + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buf, len); +} + +/* Similar to memchr() except searches a UTF-8 string 'str' of byte length 'len' + * for unicode character 'c'. + * Returns the position if found or NULL if not + */ +static const char *utf8_memchr(const char *str, int len, int c) +{ +#ifdef JIM_UTF8 + while (len) { + int sc; + int n = utf8_tounicode(str, &sc); + if (sc == c) { + return str; + } + str += n; + len -= n; + } + return NULL; +#else + return memchr(str, c, len); +#endif +} + +/** + * Searches for the first non-trim char in string (str, len) + * + * If none is found, returns just past the last char. + * + * Lengths are in bytes. + */ +static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen) +{ + while (len) { + int c; + int n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + /* Not a trim char, so stop */ + break; + } + str += n; + len -= n; + } + return str; +} + +/** + * Searches backwards for a non-trim char in string (str, len). + * + * Returns a pointer to just after the non-trim char, or NULL if not found. + * + * Lengths are in bytes. + */ +static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen) +{ + str += len; + + while (len) { + int c; + int n = utf8_prev_len(str, len); + + len -= n; + str -= n; + + n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + return str + n; + } + } + + return NULL; +} + +static const char default_trim_chars[] = " \t\n\r"; +/* sizeof() here includes the null byte */ +static int default_trim_chars_len = sizeof(default_trim_chars); + +static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *str = Jim_GetString(strObjPtr, &len); + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *newstr; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + newstr = JimFindTrimLeft(str, len, trimchars, trimcharslen); + if (newstr == str) { + return strObjPtr; + } + + return Jim_NewStringObj(interp, newstr, len - (newstr - str)); +} + +static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *nontrim; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + len = Jim_Length(strObjPtr); + nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); + + if (nontrim == NULL) { + /* All trim, so return a zero-length string */ + return Jim_NewEmptyStringObj(interp); + } + if (nontrim == strObjPtr->bytes + len) { + return strObjPtr; + } + + if (Jim_IsShared(strObjPtr)) { + strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); + } + else { + /* Can modify this string in place */ + strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; + strObjPtr->length = (nontrim - strObjPtr->bytes); + } + + return strObjPtr; +} + +static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + /* First trim left. */ + Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); + + /* Now trim right */ + strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); + + if (objPtr != strObjPtr) { + /* Note that we don't want this object to be leaked */ + Jim_IncrRefCount(objPtr); + Jim_DecrRefCount(interp, objPtr); + } + + return strObjPtr; +} + + +static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) +{ + static const char * const strclassnames[] = { + "integer", "alpha", "alnum", "ascii", "digit", + "double", "lower", "upper", "space", "xdigit", + "control", "print", "graph", "punct", + NULL + }; + enum { + STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, + STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, + STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT + }; + int strclass; + int len; + int i; + const char *str; + int (*isclassfunc)(int c) = NULL; + + if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + + str = Jim_GetString(strObjPtr, &len); + if (len == 0) { + Jim_SetResultInt(interp, !strict); + return JIM_OK; + } + + switch (strclass) { + case STR_IS_INTEGER: + { + jim_wide w; + Jim_SetResultInt(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); + return JIM_OK; + } + + case STR_IS_DOUBLE: + { + double d; + Jim_SetResultInt(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); + return JIM_OK; + } + + case STR_IS_ALPHA: isclassfunc = isalpha; break; + case STR_IS_ALNUM: isclassfunc = isalnum; break; + case STR_IS_ASCII: isclassfunc = isascii; break; + case STR_IS_DIGIT: isclassfunc = isdigit; break; + case STR_IS_LOWER: isclassfunc = islower; break; + case STR_IS_UPPER: isclassfunc = isupper; break; + case STR_IS_SPACE: isclassfunc = isspace; break; + case STR_IS_XDIGIT: isclassfunc = isxdigit; break; + case STR_IS_CONTROL: isclassfunc = iscntrl; break; + case STR_IS_PRINT: isclassfunc = isprint; break; + case STR_IS_GRAPH: isclassfunc = isgraph; break; + case STR_IS_PUNCT: isclassfunc = ispunct; break; + default: + return JIM_ERR; + } + + for (i = 0; i < len; i++) { + if (!isclassfunc(str[i])) { + Jim_SetResultInt(interp, 0); + return JIM_OK; + } + } + Jim_SetResultInt(interp, 1); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Compared String Object + * ---------------------------------------------------------------------------*/ + +/* This is strange object that allows to compare a C literal string + * with a Jim object in very short time if the same comparison is done + * multiple times. For example every time the [if] command is executed, + * Jim has to check if a given argument is "else". This comparions if + * the code has no errors are true most of the times, so we can cache + * inside the object the pointer of the string of the last matching + * comparison. Because most C compilers perform literal sharing, + * so that: char *x = "foo", char *y = "foo", will lead to x == y, + * this works pretty well even if comparisons are at different places + * inside the C code. */ + +static const Jim_ObjType comparedStringObjType = { + "compared-string", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* The only way this object is exposed to the API is via the following + * function. Returns true if the string and the object string repr. + * are the same, otherwise zero is returned. + * + * Note: this isn't binary safe, but it hardly needs to be.*/ +int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) +{ + if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) + return 1; + else { + const char *objStr = Jim_String(objPtr); + + if (strcmp(str, objStr) != 0) + return 0; + if (objPtr->typePtr != &comparedStringObjType) { + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &comparedStringObjType; + } + objPtr->internalRep.ptr = (char *)str; /*ATTENTION: const cast */ + return 1; + } +} + +static int qsortCompareStringPointers(const void *a, const void *b) +{ + char *const *sa = (char *const *)a; + char *const *sb = (char *const *)b; + + return strcmp(*sa, *sb); +} + + +/* ----------------------------------------------------------------------------- + * Source Object + * + * This object is just a string from the language point of view, but + * in the internal representation it contains the filename and line number + * where this given token was read. This information is used by + * Jim_EvalObj() if the object passed happens to be of type "source". + * + * This allows to propagate the information about line numbers and file + * names and give error messages with absolute line numbers. + * + * Note that this object uses shared strings for filenames, and the + * pointer to the filename together with the line number is taken into + * the space for the "inline" internal representation of the Jim_Object, + * so there is almost memory zero-overhead. + * + * Also the object will be converted to something else if the given + * token it represents in the source file is not something to be + * evaluated (not a script), and will be specialized in some other way, + * so the time overhead is also null. + * ---------------------------------------------------------------------------*/ + +static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType sourceObjType = { + "source", + FreeSourceInternalRep, + DupSourceInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj); +} + +void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + dupPtr->internalRep = srcPtr->internalRep; + Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); +} + +static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *fileNameObj, int lineNumber) +{ + JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); + JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typePtr != NULL")); + Jim_IncrRefCount(fileNameObj); + objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; + objPtr->internalRep.sourceValue.lineNumber = lineNumber; + objPtr->typePtr = &sourceObjType; +} + +/* ----------------------------------------------------------------------------- + * Script Object + * ---------------------------------------------------------------------------*/ + +static const Jim_ObjType scriptLineObjType = { + "scriptline", + NULL, + NULL, + NULL, + 0, +}; + +static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) +{ + Jim_Obj *objPtr; + +#ifdef DEBUG_SHOW_SCRIPT + char buf[100]; + snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc); + objPtr = Jim_NewStringObj(interp, buf, -1); +#else + objPtr = Jim_NewEmptyStringObj(interp); +#endif + objPtr->typePtr = &scriptLineObjType; + objPtr->internalRep.scriptLineValue.argc = argc; + objPtr->internalRep.scriptLineValue.line = line; + + return objPtr; +} + +#define JIM_CMDSTRUCT_EXPAND -1 + +static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result); + +static const Jim_ObjType scriptObjType = { + "script", + FreeScriptInternalRep, + DupScriptInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* The ScriptToken structure represents every token into a scriptObj. + * Every token contains an associated Jim_Obj that can be specialized + * by commands operating on it. */ +typedef struct ScriptToken +{ + int type; + Jim_Obj *objPtr; +} ScriptToken; + +/* This is the script object internal representation. An array of + * ScriptToken structures, including a pre-computed representation of the + * command length and arguments. + * + * For example the script: + * + * puts hello + * set $i $x$y [foo]BAR + * + * will produce a ScriptObj with the following Tokens: + * + * LIN 2 + * ESC puts + * ESC hello + * LIN 4 + * ESC set + * VAR i + * WRD 2 + * VAR x + * VAR y + * WRD 2 + * CMD foo + * ESC BAR + * + * "puts hello" has two args (LIN 2), composed of single tokens. + * (Note that the WRD token is omitted for the common case of a single token.) + * + * "set $i $x$y [foo]BAR" has four (LIN 4) args, the first word + * has 1 token (ESC SET), and the last has two tokens (WRD 2 CMD foo ESC BAR) + * + * The precomputation of the command structure makes Jim_Eval() faster, + * and simpler because there aren't dynamic lengths / allocations. + * + * -- {expand}/{*} handling -- + * + * Expand is handled in a special way. + * + * If a "word" begins with {*}, the word token count is -ve. + * + * For example the command: + * + * list {*}{a b} + * + * Will produce the following cmdstruct array: + * + * LIN 2 + * ESC list + * WRD -1 + * STR a b + * + * Note that the 'LIN' token also contains the source information for the + * first word of the line for error reporting purposes + * + * -- the substFlags field of the structure -- + * + * The scriptObj structure is used to represent both "script" objects + * and "subst" objects. In the second case, the there are no LIN and WRD + * tokens. Instead SEP and EOL tokens are added as-is. + * In addition, the field 'substFlags' is used to represent the flags used to turn + * the string into the internal representation used to perform the + * substitution. If this flags are not what the application requires + * the scriptObj is created again. For example the script: + * + * subst -nocommands $string + * subst -novariables $string + * + * Will recreate the internal representation of the $string object + * two times. + */ +typedef struct ScriptObj +{ + int len; /* Length as number of tokens. */ + ScriptToken *token; /* Tokens array. */ + int substFlags; /* flags used for the compilation of "subst" objects */ + int inUse; /* Used to share a ScriptObj. Currently + only used by Jim_EvalObj() as protection against + shimmering of the currently evaluated object. */ + Jim_Obj *fileNameObj; + int line; /* Line number of the first line */ +} ScriptObj; + +void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + struct ScriptObj *script = (void *)objPtr->internalRep.ptr; + + script->inUse--; + if (script->inUse != 0) + return; + for (i = 0; i < script->len; i++) { + Jim_DecrRefCount(interp, script->token[i].objPtr); + } + Jim_Free(script->token); + Jim_DecrRefCount(interp, script->fileNameObj); + Jim_Free(script); +} + +void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + /* Just returns an simple string. */ + dupPtr->typePtr = NULL; +} + +/* A simple parser token. + * All the simple tokens for the script point into the same script string rep. + */ +typedef struct +{ + const char *token; /* Pointer to the start of the token */ + int len; /* Length of this token */ + int type; /* Token type */ + int line; /* Line number */ +} ParseToken; + +/* A list of parsed tokens representing a script. + * Tokens are added to this list as the script is parsed. + * It grows as needed. + */ +typedef struct +{ + /* Start with a statically allocated list of tokens which will be expanded with realloc if needed */ + ParseToken *list; /* Array of tokens */ + int size; /* Current size of the list */ + int count; /* Number of entries used */ + ParseToken static_list[20]; /* Small initial token space to avoid allocation */ +} ParseTokenList; + +static void ScriptTokenListInit(ParseTokenList *tokenlist) +{ + tokenlist->list = tokenlist->static_list; + tokenlist->size = sizeof(tokenlist->static_list) / sizeof(ParseToken); + tokenlist->count = 0; +} + +static void ScriptTokenListFree(ParseTokenList *tokenlist) +{ + if (tokenlist->list != tokenlist->static_list) { + Jim_Free(tokenlist->list); + } +} + +/** + * Adds the new token to the tokenlist. + * The token has the given length, type and line number. + * The token list is resized as necessary. + */ +static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type, + int line) +{ + ParseToken *t; + + if (tokenlist->count == tokenlist->size) { + /* Resize the list */ + tokenlist->size *= 2; + if (tokenlist->list != tokenlist->static_list) { + tokenlist->list = + Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); + } + else { + /* The list needs to become allocated */ + tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); + memcpy(tokenlist->list, tokenlist->static_list, + tokenlist->count * sizeof(*tokenlist->list)); + } + } + t = &tokenlist->list[tokenlist->count++]; + t->token = token; + t->len = len; + t->type = type; + t->line = line; +} + +/* Counts the number of adjoining non-separator. + * + * Returns -ve if the first token is the expansion + * operator (in which case the count doesn't include + * that token). + */ +static int JimCountWordTokens(ParseToken *t) +{ + int expand = 1; + int count = 0; + + /* Is the first word {*} or {expand}? */ + if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { + if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { + /* Create an expand token */ + expand = -1; + t++; + } + } + + /* Now count non-separator words */ + while (!TOKEN_IS_SEP(t->type)) { + t++; + count++; + } + + return count * expand; +} + +/** + * Create a script/subst object from the given token. + */ +static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) +{ + Jim_Obj *objPtr; + + if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { + /* Convert the backlash escapes . */ + int len = t->len; + char *str = Jim_Alloc(len + 1); + len = JimEscape(str, t->token, len); + objPtr = Jim_NewStringObjNoAlloc(interp, str, len); + } + else { + /* REVIST: Strictly, JIM_TT_STR should replace <backslash><newline><whitespace> + * with a single space. This is currently not done. + */ + objPtr = Jim_NewStringObj(interp, t->token, t->len); + } + return objPtr; +} + +/** + * Takes a tokenlist and creates the allocated list of script tokens + * in script->token, of length script->len. + * + * Unnecessary tokens are discarded, and LINE and WORD tokens are inserted + * as required. + * + * Also sets script->line to the line number of the first token + */ +static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + /* Number of tokens so far for the current command */ + int lineargs = 0; + /* This is the first token for the current command */ + ScriptToken *linefirst; + int count; + int linenr; + +#ifdef DEBUG_SHOW_SCRIPT_TOKENS + printf("==== Tokens ====\n"); + for (i = 0; i < tokenlist->count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), + tokenlist->list[i].len, tokenlist->list[i].token); + } +#endif + + /* May need up to one extra script token for each EOL in the worst case */ + count = tokenlist->count; + for (i = 0; i < tokenlist->count; i++) { + if (tokenlist->list[i].type == JIM_TT_EOL) { + count++; + } + } + linenr = script->line = tokenlist->list[0].line; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); + + /* This is the first token for the current command */ + linefirst = token++; + + for (i = 0; i < tokenlist->count; ) { + /* Look ahead to find out how many tokens make up the next word */ + int wordtokens; + + /* Skip any leading separators */ + while (tokenlist->list[i].type == JIM_TT_SEP) { + i++; + } + + wordtokens = JimCountWordTokens(tokenlist->list + i); + + if (wordtokens == 0) { + /* None, so at end of line */ + if (lineargs) { + linefirst->type = JIM_TT_LINE; + linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); + Jim_IncrRefCount(linefirst->objPtr); + + /* Reset for new line */ + lineargs = 0; + linefirst = token++; + } + i++; + continue; + } + else if (wordtokens != 1) { + /* More than 1, or {expand}, so insert a WORD token */ + token->type = JIM_TT_WORD; + token->objPtr = Jim_NewIntObj(interp, wordtokens); + Jim_IncrRefCount(token->objPtr); + token++; + if (wordtokens < 0) { + /* Skip the expand token */ + i++; + wordtokens = -wordtokens - 1; + lineargs--; + } + } + + if (lineargs == 0) { + /* First real token on the line, so record the line number */ + linenr = tokenlist->list[i].line; + } + lineargs++; + + /* Add each non-separator word token to the line */ + while (wordtokens--) { + const ParseToken *t = &tokenlist->list[i++]; + + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + + /* Every object is initially a string, but the + * internal type may be specialized during execution of the + * script. */ + JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); + token++; + } + } + + if (lineargs == 0) { + token--; + } + + script->len = token - script->token; + + assert(script->len < count); + +#ifdef DEBUG_SHOW_SCRIPT + printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); + for (i = 0; i < script->len; i++) { + const ScriptToken *t = &script->token[i]; + printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } +#endif + +} + +/** + * Similar to ScriptObjAddTokens(), but for subst objects. + */ +static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); + + for (i = 0; i < tokenlist->count; i++) { + const ParseToken *t = &tokenlist->list[i]; + + /* Create a token for 't' */ + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + token++; + } + + script->len = i; +} + +/* This method takes the string representation of an object + * as a Tcl script, and generates the pre-parsed internal representation + * of the script. */ +static int SetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, struct JimParseResult *result) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script; + ParseTokenList tokenlist; + int line = 1; + + /* Try to get information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + line = objPtr->internalRep.sourceValue.lineNumber; + } + + /* Initially parse the script into tokens (in tokenlist) */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, line); + while (!parser.eof) { + JimParseScript(&parser); + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + if (result && parser.missing != ' ') { + ScriptTokenListFree(&tokenlist); + result->missing = parser.missing; + result->line = parser.missingline; + return JIM_ERR; + } + + /* Add a final EOF token */ + ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); + + /* Create the "real" script tokens from the initial token list */ + script = Jim_Alloc(sizeof(*script)); + memset(script, 0, sizeof(*script)); + script->inUse = 1; + script->line = line; + if (objPtr->typePtr == &sourceObjType) { + script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + } + else { + script->fileNameObj = interp->emptyObj; + } + Jim_IncrRefCount(script->fileNameObj); + + ScriptObjAddTokens(interp, script, &tokenlist); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + + /* Free the old internal rep and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; + + return JIM_OK; +} + +ScriptObj *Jim_GetScript(Jim_Interp *interp, Jim_Obj *objPtr) +{ + struct ScriptObj *script = Jim_GetIntRepPtr(objPtr); + + if (objPtr->typePtr != &scriptObjType || script->substFlags) { + SetScriptFromAny(interp, objPtr, NULL); + } + return (ScriptObj *) Jim_GetIntRepPtr(objPtr); +} + +/* ----------------------------------------------------------------------------- + * Commands + * ---------------------------------------------------------------------------*/ +static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) +{ + cmdPtr->inUse++; +} + +static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr) +{ + if (--cmdPtr->inUse == 0) { + if (cmdPtr->isproc) { + Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr); + Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr); + if (cmdPtr->u.proc.staticVars) { + Jim_FreeHashTable(cmdPtr->u.proc.staticVars); + Jim_Free(cmdPtr->u.proc.staticVars); + } + if (cmdPtr->u.proc.prevCmd) { + /* Delete any pushed command too */ + JimDecrCmdRefCount(interp, cmdPtr->u.proc.prevCmd); + } + } + else { + /* native (C) */ + if (cmdPtr->u.native.delProc) { + cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); + } + } + Jim_Free(cmdPtr); + } +} + +/* Commands HashTable Type. + * + * Keys are dynamic allocated strings, Values are Jim_Cmd structures. */ +static void JimCommandsHT_ValDestructor(void *interp, void *val) +{ + JimDecrCmdRefCount(interp, val); +} + +static const Jim_HashTableType JimCommandsHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimCommandsHT_ValDestructor /* val destructor */ +}; + +/* ------------------------- Commands related functions --------------------- */ + +int Jim_CreateCommand(Jim_Interp *interp, const char *cmdName, + Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc) +{ + Jim_Cmd *cmdPtr; + + if (Jim_DeleteHashEntry(&interp->commands, cmdName) != JIM_ERR) { + /* Command existed so incr proc epoch */ + Jim_InterpIncrProcEpoch(interp); + } + + cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); + + /* Store the new details for this proc */ + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->u.native.delProc = delProc; + cmdPtr->u.native.cmdProc = cmdProc; + cmdPtr->u.native.privData = privData; + + Jim_AddHashEntry(&interp->commands, cmdName, cmdPtr); + + /* There is no need to increment the 'proc epoch' because + * creation of a new procedure can never affect existing + * cached commands. We don't do negative caching. */ + return JIM_OK; +} + +static int JimCreateProcedure(Jim_Interp *interp, Jim_Obj *cmdName, + Jim_Obj *argListObjPtr, Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr) +{ + Jim_Cmd *cmdPtr; + Jim_HashEntry *he; + int argListLen; + int i; + + if (JimValidName(interp, "procedure", cmdName) != JIM_OK) { + return JIM_ERR; + } + + argListLen = Jim_ListLength(interp, argListObjPtr); + + /* Allocate space for both the command pointer and the arg list */ + cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->isproc = 1; + cmdPtr->u.proc.argListObjPtr = argListObjPtr; + cmdPtr->u.proc.argListLen = argListLen; + cmdPtr->u.proc.bodyObjPtr = bodyObjPtr; + cmdPtr->u.proc.argsPos = -1; + cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1); + Jim_IncrRefCount(argListObjPtr); + Jim_IncrRefCount(bodyObjPtr); + + /* Create the statics hash table. */ + if (staticsListObjPtr) { + int len, i; + + len = Jim_ListLength(interp, staticsListObjPtr); + if (len != 0) { + cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); + for (i = 0; i < len; i++) { + Jim_Obj *objPtr = 0, *initObjPtr = 0, *nameObjPtr = 0; + Jim_Var *varPtr; + int subLen; + + Jim_ListIndex(interp, staticsListObjPtr, i, &objPtr, JIM_NONE); + /* Check if it's composed of two elements. */ + subLen = Jim_ListLength(interp, objPtr); + if (subLen == 1 || subLen == 2) { + /* Try to get the variable value from the current + * environment. */ + Jim_ListIndex(interp, objPtr, 0, &nameObjPtr, JIM_NONE); + if (subLen == 1) { + initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); + if (initObjPtr == NULL) { + Jim_SetResultFormatted(interp, + "variable for initialization of static \"%#s\" not found in the local context", + nameObjPtr); + goto err; + } + } + else { + Jim_ListIndex(interp, objPtr, 1, &initObjPtr, JIM_NONE); + } + if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { + goto err; + } + + varPtr = Jim_Alloc(sizeof(*varPtr)); + varPtr->objPtr = initObjPtr; + Jim_IncrRefCount(initObjPtr); + varPtr->linkFramePtr = NULL; + if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars, + Jim_String(nameObjPtr), varPtr) != JIM_OK) { + Jim_SetResultFormatted(interp, + "static variable name \"%#s\" duplicated in statics list", nameObjPtr); + Jim_DecrRefCount(interp, initObjPtr); + Jim_Free(varPtr); + goto err; + } + } + else { + Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"", + objPtr); + goto err; + } + } + } + } + + /* Parse the args out into arglist, validating as we go */ + /* Examine the argument list for default parameters and 'args' */ + for (i = 0; i < argListLen; i++) { + Jim_Obj *argPtr; + Jim_Obj *nameObjPtr; + Jim_Obj *defaultObjPtr; + int len; + int n = 1; + + /* Examine a parameter */ + Jim_ListIndex(interp, argListObjPtr, i, &argPtr, JIM_NONE); + len = Jim_ListLength(interp, argPtr); + if (len == 0) { + Jim_SetResultString(interp, "procedure has argument with no name", -1); + goto err; + } + if (len > 2) { + Jim_SetResultString(interp, "procedure has argument with too many fields", -1); + goto err; + } + + if (len == 2) { + /* Optional parameter */ + Jim_ListIndex(interp, argPtr, 0, &nameObjPtr, JIM_NONE); + Jim_ListIndex(interp, argPtr, 1, &defaultObjPtr, JIM_NONE); + } + else { + /* Required parameter */ + nameObjPtr = argPtr; + defaultObjPtr = NULL; + } + + + if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) { + if (cmdPtr->u.proc.argsPos >= 0) { + Jim_SetResultString(interp, "procedure has 'args' specified more than once", -1); + goto err; + } + cmdPtr->u.proc.argsPos = i; + } + else { + if (len == 2) { + cmdPtr->u.proc.optArity += n; + } + else { + cmdPtr->u.proc.reqArity += n; + } + } + + cmdPtr->u.proc.arglist[i].nameObjPtr = nameObjPtr; + cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr; + } + + /* Add the new command */ + + /* It may already exist, so we try to delete the old one. + * Note that reference count means that it won't be deleted yet if + * it exists in the call stack. + * + * BUT, if 'local' is in force, instead of deleting the existing + * proc, we stash a reference to the old proc here. + */ + he = Jim_FindHashEntry(&interp->commands, Jim_String(cmdName)); + if (he) { + /* There was an old procedure with the same name, this requires + * a 'proc epoch' update. */ + + /* If a procedure with the same name didn't existed there is no need + * to increment the 'proc epoch' because creation of a new procedure + * can never affect existing cached commands. We don't do + * negative caching. */ + Jim_InterpIncrProcEpoch(interp); + } + + if (he && interp->local) { + /* Just push this proc over the top of the previous one */ + cmdPtr->u.proc.prevCmd = he->u.val; + he->u.val = cmdPtr; + } + else { + if (he) { + /* Replace the existing proc */ + Jim_DeleteHashEntry(&interp->commands, Jim_String(cmdName)); + } + + Jim_AddHashEntry(&interp->commands, Jim_String(cmdName), cmdPtr); + } + + /* Unlike Tcl, set the name of the proc as the result */ + Jim_SetResult(interp, cmdName); + return JIM_OK; + + err: + if (cmdPtr->u.proc.staticVars) { + Jim_FreeHashTable(cmdPtr->u.proc.staticVars); + } + Jim_Free(cmdPtr->u.proc.staticVars); + Jim_DecrRefCount(interp, argListObjPtr); + Jim_DecrRefCount(interp, bodyObjPtr); + Jim_Free(cmdPtr); + return JIM_ERR; +} + +int Jim_DeleteCommand(Jim_Interp *interp, const char *cmdName) +{ + if (Jim_DeleteHashEntry(&interp->commands, cmdName) == JIM_ERR) + return JIM_ERR; + Jim_InterpIncrProcEpoch(interp); + return JIM_OK; +} + +int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName) +{ + Jim_HashEntry *he; + + /* Does it exist? */ + he = Jim_FindHashEntry(&interp->commands, oldName); + if (he == NULL) { + Jim_SetResultFormatted(interp, "can't %s \"%s\": command doesn't exist", + newName[0] ? "rename" : "delete", oldName); + return JIM_ERR; + } + + if (newName[0] == '\0') /* Delete! */ + return Jim_DeleteCommand(interp, oldName); + + /* rename */ + if (Jim_FindHashEntry(&interp->commands, newName)) { + Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); + return JIM_ERR; + } + + /* Add the new name first */ + JimIncrCmdRefCount(he->u.val); + Jim_AddHashEntry(&interp->commands, newName, he->u.val); + + /* Now remove the old name */ + Jim_DeleteHashEntry(&interp->commands, oldName); + + /* Increment the epoch */ + Jim_InterpIncrProcEpoch(interp); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Command object + * ---------------------------------------------------------------------------*/ + +static int SetCommandFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType commandObjType = { + "command", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +int SetCommandFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_HashEntry *he; + const char *cmdName; + + /* Get the string representation */ + cmdName = Jim_String(objPtr); + /* Lookup this name into the commands hash table */ + he = Jim_FindHashEntry(&interp->commands, cmdName); + if (he == NULL) + return JIM_ERR; + + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &commandObjType; + objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; + objPtr->internalRep.cmdValue.cmdPtr = (void *)he->u.val; + return JIM_OK; +} + +/* This function returns the command structure for the command name + * stored in objPtr. It tries to specialize the objPtr to contain + * a cached info instead to perform the lookup into the hash table + * every time. The information cached may not be uptodate, in such + * a case the lookup is performed and the cache updated. + * + * Respects the 'upcall' setting + */ +Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + Jim_Cmd *cmd; + + if ((objPtr->typePtr != &commandObjType || + objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch) && + SetCommandFromAny(interp, objPtr) == JIM_ERR) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); + } + return NULL; + } + cmd = objPtr->internalRep.cmdValue.cmdPtr; + while (cmd->isproc && cmd->u.proc.upcall) { + cmd = cmd->u.proc.prevCmd; + } + return cmd; +} + +/* ----------------------------------------------------------------------------- + * Variables + * ---------------------------------------------------------------------------*/ + +/* Variables HashTable Type. + * + * Keys are dynamic allocated strings, Values are Jim_Var structures. */ +static void JimVariablesHTValDestructor(void *interp, void *val) +{ + Jim_Var *varPtr = (void *)val; + + Jim_DecrRefCount(interp, varPtr->objPtr); + Jim_Free(val); +} + +static const Jim_HashTableType JimVariablesHashTableType = { + JimStringCopyHTHashFunction, /* hash function */ + JimStringCopyHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimStringCopyHTKeyCompare, /* key compare */ + JimStringCopyHTKeyDestructor, /* key destructor */ + JimVariablesHTValDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Variable object + * ---------------------------------------------------------------------------*/ + +#define JIM_DICT_SUGAR 100 /* Only returned by SetVariableFromAny() */ + +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType variableObjType = { + "variable", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* Return true if the string "str" looks like syntax sugar for [dict]. I.e. + * is in the form "varname(key)". */ +static int JimNameIsDictSugar(const char *str, int len) +{ + if (len && str[len - 1] == ')' && strchr(str, '(') != NULL) + return 1; + return 0; +} + +/** + * Check that the name does not contain embedded nulls. + * + * Variable and procedure names are maniplated as null terminated strings, so + * don't allow names with embedded nulls. + */ +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) +{ + /* Variable names and proc names can't contain embedded nulls */ + if (nameObjPtr->typePtr != &variableObjType) { + int len; + const char *str = Jim_GetString(nameObjPtr, &len); + if (memchr(str, '\0', len)) { + Jim_SetResultFormatted(interp, "%s name contains embedded null", type); + return JIM_ERR; + } + } + return JIM_OK; +} + +/* This method should be called only by the variable API. + * It returns JIM_OK on success (variable already exists), + * JIM_ERR if it does not exists, JIM_DICT_SUGAR if it's not + * a variable name, but syntax glue for [dict] i.e. the last + * character is ')' */ +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + Jim_HashEntry *he; + const char *varName; + int len; + Jim_CallFrame *framePtr = interp->framePtr; + + /* Check if the object is already an uptodate variable */ + if (objPtr->typePtr == &variableObjType && + objPtr->internalRep.varValue.callFrameId == framePtr->id) { + return JIM_OK; /* nothing to do */ + } + + if (objPtr->typePtr == &dictSubstObjType) { + return JIM_DICT_SUGAR; + } + + if (JimValidName(interp, "variable", objPtr) != JIM_OK) { + return JIM_ERR; + } + + /* Get the string representation */ + varName = Jim_GetString(objPtr, &len); + + /* Make sure it's not syntax glue to get/set dict. */ + if (JimNameIsDictSugar(varName, len)) { + return JIM_DICT_SUGAR; + } + + if (varName[0] == ':' && varName[1] == ':') { + framePtr = interp->topFramePtr; + he = Jim_FindHashEntry(&framePtr->vars, varName + 2); + if (he == NULL) { + return JIM_ERR; + } + } + else { + /* Lookup this name into the variables hash table */ + he = Jim_FindHashEntry(&framePtr->vars, varName); + if (he == NULL) { + /* Try with static vars. */ + if (framePtr->staticVars == NULL) + return JIM_ERR; + if (!(he = Jim_FindHashEntry(framePtr->staticVars, varName))) + return JIM_ERR; + } + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &variableObjType; + objPtr->internalRep.varValue.callFrameId = framePtr->id; + objPtr->internalRep.varValue.varPtr = (void *)he->u.val; + return JIM_OK; +} + +/* -------------------- Variables related functions ------------------------- */ +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr); +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags); + +/* For now that's dummy. Variables lookup should be optimized + * in many ways, with caching of lookups, and possibly with + * a table of pre-allocated vars in every CallFrame for local vars. + * All the caching should also have an 'epoch' mechanism similar + * to the one used by Tcl for procedures lookup caching. */ + +int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) +{ + const char *name; + Jim_Var *var; + int err; + + if ((err = SetVariableFromAny(interp, nameObjPtr)) != JIM_OK) { + Jim_CallFrame *framePtr = interp->framePtr; + + /* Check for [dict] syntax sugar. */ + if (err == JIM_DICT_SUGAR) + return JimDictSugarSet(interp, nameObjPtr, valObjPtr); + + if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) { + return JIM_ERR; + } + + /* New variable to create */ + name = Jim_String(nameObjPtr); + + var = Jim_Alloc(sizeof(*var)); + var->objPtr = valObjPtr; + Jim_IncrRefCount(valObjPtr); + var->linkFramePtr = NULL; + /* Insert the new variable */ + if (name[0] == ':' && name[1] == ':') { + /* Into the top level frame */ + framePtr = interp->topFramePtr; + Jim_AddHashEntry(&framePtr->vars, name + 2, var); + } + else { + Jim_AddHashEntry(&framePtr->vars, name, var); + } + /* Make the object int rep a variable */ + Jim_FreeIntRep(interp, nameObjPtr); + nameObjPtr->typePtr = &variableObjType; + nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; + nameObjPtr->internalRep.varValue.varPtr = var; + } + else { + var = nameObjPtr->internalRep.varValue.varPtr; + if (var->linkFramePtr == NULL) { + Jim_IncrRefCount(valObjPtr); + Jim_DecrRefCount(interp, var->objPtr); + var->objPtr = valObjPtr; + } + else { /* Else handle the link */ + Jim_CallFrame *savedCallFrame; + + savedCallFrame = interp->framePtr; + interp->framePtr = var->linkFramePtr; + err = Jim_SetVariable(interp, var->objPtr, valObjPtr); + interp->framePtr = savedCallFrame; + if (err != JIM_OK) + return err; + } + } + return JIM_OK; +} + +int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_Obj *nameObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, objPtr); + Jim_DecrRefCount(interp, nameObjPtr); + return result; +} + +int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_CallFrame *savedFramePtr; + int result; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + result = Jim_SetVariableStr(interp, name, objPtr); + interp->framePtr = savedFramePtr; + return result; +} + +int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) +{ + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + valObjPtr = Jim_NewStringObj(interp, val, -1); + Jim_IncrRefCount(nameObjPtr); + Jim_IncrRefCount(valObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + Jim_DecrRefCount(interp, valObjPtr); + return result; +} + +int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, + Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) +{ + const char *varName; + int len; + + varName = Jim_GetString(nameObjPtr, &len); + + if (varName[0] == ':' && varName[1] == ':') { + /* Linking a global var does nothing */ + return JIM_OK; + } + + if (JimNameIsDictSugar(varName, len)) { + Jim_SetResultString(interp, "Dict key syntax invalid as link source", -1); + return JIM_ERR; + } + + /* Check for an existing variable or link */ + if (SetVariableFromAny(interp, nameObjPtr) == JIM_OK) { + Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); + return JIM_ERR; + } + + /* It exists, but is a link, so delete the link */ + varPtr->linkFramePtr = NULL; + } + + /* Check for cycles. */ + if (interp->framePtr == targetCallFrame) { + Jim_Obj *objPtr = targetNameObjPtr; + Jim_Var *varPtr; + + /* Cycles are only possible with 'uplevel 0' */ + while (1) { + if (Jim_StringEqObj(objPtr, nameObjPtr)) { + Jim_SetResultString(interp, "can't upvar from variable to itself", -1); + return JIM_ERR; + } + if (SetVariableFromAny(interp, objPtr) != JIM_OK) + break; + varPtr = objPtr->internalRep.varValue.varPtr; + if (varPtr->linkFramePtr != targetCallFrame) + break; + objPtr = varPtr->objPtr; + } + } + + /* Perform the binding */ + Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); + /* We are now sure 'nameObjPtr' type is variableObjType */ + nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; + return JIM_OK; +} + +/* Return the Jim_Obj pointer associated with a variable name, + * or NULL if the variable was not found in the current context. + * The same optimization discussed in the comment to the + * 'SetVariable' function should apply here. + * + * If JIM_UNSHARED is set and the variable is an array element (dict sugar) + * in a dictionary which is shared, the array variable value is duplicated first. + * This allows the array element to be updated (e.g. append, lappend) without + * affecting other references to the dictionary. + */ +Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + switch (SetVariableFromAny(interp, nameObjPtr)) { + case JIM_OK:{ + Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + return varPtr->objPtr; + } + else { + Jim_Obj *objPtr; + + /* The variable is a link? Resolve it. */ + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = varPtr->linkFramePtr; + objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); + interp->framePtr = savedCallFrame; + if (objPtr) { + return objPtr; + } + /* Error, so fall through to the error message */ + } + } + break; + + case JIM_DICT_SUGAR: + /* [dict] syntax sugar. */ + return JimDictSugarGet(interp, nameObjPtr, flags); + } + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); + } + return NULL; +} + +Jim_Obj *Jim_GetGlobalVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariable(interp, nameObjPtr, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +Jim_Obj *Jim_GetVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_Obj *nameObjPtr, *varObjPtr; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + varObjPtr = Jim_GetVariable(interp, nameObjPtr, flags); + Jim_DecrRefCount(interp, nameObjPtr); + return varObjPtr; +} + +Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariableStr(interp, name, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +/* Unset a variable. + * Note: On success unset invalidates all the variable objects created + * in the current call frame incrementing. */ +int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + const char *name; + Jim_Var *varPtr; + int retval; + + retval = SetVariableFromAny(interp, nameObjPtr); + if (retval == JIM_DICT_SUGAR) { + /* [dict] syntax sugar. */ + return JimDictSugarSet(interp, nameObjPtr, NULL); + } + else if (retval == JIM_OK) { + varPtr = nameObjPtr->internalRep.varValue.varPtr; + + /* If it's a link call UnsetVariable recursively */ + if (varPtr->linkFramePtr) { + Jim_CallFrame *savedCallFrame; + + savedCallFrame = interp->framePtr; + interp->framePtr = varPtr->linkFramePtr; + retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); + interp->framePtr = savedCallFrame; + } + else { + Jim_CallFrame *framePtr = interp->framePtr; + + name = Jim_String(nameObjPtr); + if (name[0] == ':' && name[1] == ':') { + framePtr = interp->topFramePtr; + name += 2; + } + retval = Jim_DeleteHashEntry(&framePtr->vars, name); + if (retval == JIM_OK) { + /* Change the callframe id, invalidating var lookup caching */ + JimChangeCallFrameId(interp, framePtr); + } + } + } + if (retval != JIM_OK && (flags & JIM_ERRMSG)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); + } + return retval; +} + +/* ---------- Dict syntax sugar (similar to array Tcl syntax) -------------- */ + +/* Given a variable name for [dict] operation syntax sugar, + * this function returns two objects, the first with the name + * of the variable to set, and the second with the rispective key. + * For example "foo(bar)" will return objects with string repr. of + * "foo" and "bar". + * + * The returned objects have refcount = 1. The function can't fail. */ +static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr) +{ + const char *str, *p; + int len, keyLen; + Jim_Obj *varObjPtr, *keyObjPtr; + + str = Jim_GetString(objPtr, &len); + + p = strchr(str, '('); + JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str)); + + varObjPtr = Jim_NewStringObj(interp, str, p - str); + + p++; + keyLen = (str + len) - p; + if (str[len - 1] == ')') { + keyLen--; + } + + /* Create the objects with the variable name and key. */ + keyObjPtr = Jim_NewStringObj(interp, p, keyLen); + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + *varPtrPtr = varObjPtr; + *keyPtrPtr = keyObjPtr; +} + +/* Helper of Jim_SetVariable() to deal with dict-syntax variable names. + * Also used by Jim_UnsetVariable() with valObjPtr = NULL. */ +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr) +{ + int err; + + SetDictSubstFromAny(interp, objPtr); + + err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_ERRMSG); + + if (err == JIM_OK) { + /* Don't keep an extra ref to the result */ + Jim_SetEmptyResult(interp); + } + else { + if (!valObjPtr) { + /* Better error message for unset a(2) where a exists but a(2) doesn't */ + if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", + objPtr); + return err; + } + } + /* Make the error more informative and Tcl-compatible */ + Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", + (valObjPtr ? "set" : "unset"), objPtr); + } + return err; +} + +/** + * Expands the array variable (dict sugar) and returns the result, or NULL on error. + * + * If JIM_UNSHARED is set and the dictionary is shared, it will be duplicated + * and stored back to the variable before expansion. + */ +static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr, + Jim_Obj *keyObjPtr, int flags) +{ + Jim_Obj *dictObjPtr; + Jim_Obj *resObjPtr = NULL; + int ret; + + dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG); + if (!dictObjPtr) { + return NULL; + } + + ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); + if (ret != JIM_OK) { + resObjPtr = NULL; + if (ret < 0) { + Jim_SetResultFormatted(interp, + "can't read \"%#s(%#s)\": variable isn't array", varObjPtr, keyObjPtr); + } + else { + Jim_SetResultFormatted(interp, + "can't read \"%#s(%#s)\": no such element in array", varObjPtr, keyObjPtr); + } + } + else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { + dictObjPtr = Jim_DuplicateObj(interp, dictObjPtr); + if (Jim_SetVariable(interp, varObjPtr, dictObjPtr) != JIM_OK) { + /* This can probably never happen */ + JimPanic((1, "SetVariable failed for JIM_UNSHARED")); + } + /* We know that the key exists. Get the result in the now-unshared dictionary */ + Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); + } + + return resObjPtr; +} + +/* Helper of Jim_GetVariable() to deal with dict-syntax variable names */ +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + SetDictSubstFromAny(interp, objPtr); + + return JimDictExpandArrayVariable(interp, + objPtr->internalRep.dictSubstValue.varNameObjPtr, + objPtr->internalRep.dictSubstValue.indexObjPtr, flags); +} + +/* --------- $var(INDEX) substitution, using a specialized object ----------- */ + +void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); +} + +void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + dupPtr->internalRep.dictSubstValue.varNameObjPtr = + srcPtr->internalRep.dictSubstValue.varNameObjPtr; + dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; + dupPtr->typePtr = &dictSubstObjType; +} + +/* Note: The object *must* be in dict-sugar format */ +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &dictSubstObjType) { + Jim_Obj *varObjPtr, *keyObjPtr; + + if (objPtr->typePtr == &interpolatedObjType) { + /* An interpolated object in dict-sugar form */ + + const ScriptToken *token = objPtr->internalRep.twoPtrValue.ptr1; + + varObjPtr = token[0].objPtr; + keyObjPtr = objPtr->internalRep.twoPtrValue.ptr2; + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + } + else { + JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr); + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictSubstObjType; + objPtr->internalRep.dictSubstValue.varNameObjPtr = varObjPtr; + objPtr->internalRep.dictSubstValue.indexObjPtr = keyObjPtr; + } +} + +/* This function is used to expand [dict get] sugar in the form + * of $var(INDEX). The function is mainly used by Jim_EvalObj() + * to deal with tokens of type JIM_TT_DICTSUGAR. objPtr points to an + * object that is *guaranteed* to be in the form VARNAME(INDEX). + * The 'index' part is [subst]ituted, and is used to lookup a key inside + * the [dict]ionary contained in variable VARNAME. */ +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resObjPtr = NULL; + Jim_Obj *substKeyObjPtr = NULL; + + SetDictSubstFromAny(interp, objPtr); + + if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr, + &substKeyObjPtr, JIM_NONE) + != JIM_OK) { + return NULL; + } + Jim_IncrRefCount(substKeyObjPtr); + resObjPtr = + JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + substKeyObjPtr, 0); + Jim_DecrRefCount(interp, substKeyObjPtr); + + return resObjPtr; +} + +static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resultObjPtr; + + if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { + /* Note that the result has a ref count of 1, but we need a ref count of 0 */ + resultObjPtr->refCount--; + return resultObjPtr; + } + return NULL; +} + +/* ----------------------------------------------------------------------------- + * CallFrame + * ---------------------------------------------------------------------------*/ + +static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent) +{ + Jim_CallFrame *cf; + + if (interp->freeFramesList) { + cf = interp->freeFramesList; + interp->freeFramesList = cf->nextFramePtr; + } + else { + cf = Jim_Alloc(sizeof(*cf)); + cf->vars.table = NULL; + } + + cf->id = interp->callFrameEpoch++; + cf->parentCallFrame = parent; + cf->level = parent ? parent->level + 1 : 0; + cf->argv = NULL; + cf->argc = 0; + cf->procArgsObjPtr = NULL; + cf->procBodyObjPtr = NULL; + cf->nextFramePtr = NULL; + cf->staticVars = NULL; + if (cf->vars.table == NULL) + Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); + return cf; +} + +/* Used to invalidate every caching related to callframe stability. */ +static void JimChangeCallFrameId(Jim_Interp *interp, Jim_CallFrame *cf) +{ + cf->id = interp->callFrameEpoch++; +} + +#define JIM_FCF_NONE 0 /* no flags */ +#define JIM_FCF_NOHT 1 /* don't free the hash table */ +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int flags) +{ + if (cf->procArgsObjPtr) + Jim_DecrRefCount(interp, cf->procArgsObjPtr); + if (cf->procBodyObjPtr) + Jim_DecrRefCount(interp, cf->procBodyObjPtr); + if (!(flags & JIM_FCF_NOHT)) + Jim_FreeHashTable(&cf->vars); + else { + int i; + Jim_HashEntry **table = cf->vars.table, *he; + + for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { + he = table[i]; + while (he != NULL) { + Jim_HashEntry *nextEntry = he->next; + Jim_Var *varPtr = (void *)he->u.val; + + Jim_DecrRefCount(interp, varPtr->objPtr); + Jim_Free(he->u.val); + Jim_Free((void *)he->key); /* ATTENTION: const cast */ + Jim_Free(he); + table[i] = NULL; + he = nextEntry; + } + } + cf->vars.used = 0; + } + cf->nextFramePtr = interp->freeFramesList; + interp->freeFramesList = cf; +} + +/* ----------------------------------------------------------------------------- + * References + * ---------------------------------------------------------------------------*/ +#ifdef JIM_REFERENCES + +/* References HashTable Type. + * + * Keys are jim_wide integers, dynamically allocated for now but in the + * future it's worth to cache this 8 bytes objects. Values are poitners + * to Jim_References. */ +static void JimReferencesHTValDestructor(void *interp, void *val) +{ + Jim_Reference *refPtr = (void *)val; + + Jim_DecrRefCount(interp, refPtr->objPtr); + if (refPtr->finalizerCmdNamePtr != NULL) { + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + } + Jim_Free(val); +} + +static unsigned int JimReferencesHTHashFunction(const void *key) +{ + /* Only the least significant bits are used. */ + const jim_wide *widePtr = key; + unsigned int intValue = (unsigned int)*widePtr; + + return Jim_IntHashFunction(intValue); +} + +static const void *JimReferencesHTKeyDup(void *privdata, const void *key) +{ + void *copy = Jim_Alloc(sizeof(jim_wide)); + + JIM_NOTUSED(privdata); + + memcpy(copy, key, sizeof(jim_wide)); + return copy; +} + +static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return memcmp(key1, key2, sizeof(jim_wide)) == 0; +} + +static void JimReferencesHTKeyDestructor(void *privdata, const void *key) +{ + JIM_NOTUSED(privdata); + + Jim_Free((void *)key); +} + +static const Jim_HashTableType JimReferencesHashTableType = { + JimReferencesHTHashFunction, /* hash function */ + JimReferencesHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimReferencesHTKeyCompare, /* key compare */ + JimReferencesHTKeyDestructor, /* key destructor */ + JimReferencesHTValDestructor /* val destructor */ +}; + +/* ----------------------------------------------------------------------------- + * Reference object type and References API + * ---------------------------------------------------------------------------*/ + +/* The string representation of references has two features in order + * to make the GC faster. The first is that every reference starts + * with a non common character '<', in order to make the string matching + * faster. The second is that the reference string rep is 42 characters + * in length, this allows to avoid to check every object with a string + * repr < 42, and usually there aren't many of these objects. */ + +#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) + +static int JimFormatReference(char *buf, Jim_Reference *refPtr, jim_wide id) +{ + const char *fmt = "<reference.<%s>.%020" JIM_WIDE_MODIFIER ">"; + + sprintf(buf, fmt, refPtr->tag, id); + return JIM_REFERENCE_SPACE; +} + +static void UpdateStringOfReference(struct Jim_Obj *objPtr); + +static const Jim_ObjType referenceObjType = { + "reference", + NULL, + NULL, + UpdateStringOfReference, + JIM_TYPE_REFERENCES, +}; + +void UpdateStringOfReference(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_REFERENCE_SPACE + 1]; + Jim_Reference *refPtr; + + refPtr = objPtr->internalRep.refValue.refPtr; + len = JimFormatReference(buf, refPtr, objPtr->internalRep.refValue.id); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +/* returns true if 'c' is a valid reference tag character. + * i.e. inside the range [_a-zA-Z0-9] */ +static int isrefchar(int c) +{ + return (c == '_' || isalnum(c)); +} + +static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + jim_wide wideValue; + int i, len; + const char *str, *start, *end; + char refId[21]; + Jim_Reference *refPtr; + Jim_HashEntry *he; + + /* Get the string representation */ + str = Jim_GetString(objPtr, &len); + /* Check if it looks like a reference */ + if (len < JIM_REFERENCE_SPACE) + goto badformat; + /* Trim spaces */ + start = str; + end = str + len - 1; + while (*start == ' ') + start++; + while (*end == ' ' && end > start) + end--; + if (end - start + 1 != JIM_REFERENCE_SPACE) + goto badformat; + /* <reference.<1234567>.%020> */ + if (memcmp(start, "<reference.<", 12) != 0) + goto badformat; + if (start[12 + JIM_REFERENCE_TAGLEN] != '>' || end[0] != '>') + goto badformat; + /* The tag can't contain chars other than a-zA-Z0-9 + '_'. */ + for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { + if (!isrefchar(start[12 + i])) + goto badformat; + } + /* Extract info from the reference. */ + memcpy(refId, start + 14 + JIM_REFERENCE_TAGLEN, 20); + refId[20] = '\0'; + /* Try to convert the ID into a jim_wide */ + if (Jim_StringToWide(refId, &wideValue, 10) != JIM_OK) + goto badformat; + /* Check if the reference really exists! */ + he = Jim_FindHashEntry(&interp->references, &wideValue); + if (he == NULL) { + Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); + return JIM_ERR; + } + refPtr = he->u.val; + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &referenceObjType; + objPtr->internalRep.refValue.id = wideValue; + objPtr->internalRep.refValue.refPtr = refPtr; + return JIM_OK; + + badformat: + Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); + return JIM_ERR; +} + +/* Returns a new reference pointing to objPtr, having cmdNamePtr + * as finalizer command (or NULL if there is no finalizer). + * The returned reference object has refcount = 0. */ +Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) +{ + struct Jim_Reference *refPtr; + jim_wide wideValue = interp->referenceNextId; + Jim_Obj *refObjPtr; + const char *tag; + int tagLen, i; + + /* Perform the Garbage Collection if needed. */ + Jim_CollectIfNeeded(interp); + + refPtr = Jim_Alloc(sizeof(*refPtr)); + refPtr->objPtr = objPtr; + Jim_IncrRefCount(objPtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + if (cmdNamePtr) + Jim_IncrRefCount(cmdNamePtr); + Jim_AddHashEntry(&interp->references, &wideValue, refPtr); + refObjPtr = Jim_NewObj(interp); + refObjPtr->typePtr = &referenceObjType; + refObjPtr->bytes = NULL; + refObjPtr->internalRep.refValue.id = interp->referenceNextId; + refObjPtr->internalRep.refValue.refPtr = refPtr; + interp->referenceNextId++; + /* Set the tag. Trimmed at JIM_REFERENCE_TAGLEN. Everything + * that does not pass the 'isrefchar' test is replaced with '_' */ + tag = Jim_GetString(tagPtr, &tagLen); + if (tagLen > JIM_REFERENCE_TAGLEN) + tagLen = JIM_REFERENCE_TAGLEN; + for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { + if (i < tagLen && isrefchar(tag[i])) + refPtr->tag[i] = tag[i]; + else + refPtr->tag[i] = '_'; + } + refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; + return refObjPtr; +} + +Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) + return NULL; + return objPtr->internalRep.refValue.refPtr; +} + +int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + Jim_IncrRefCount(cmdNamePtr); + if (refPtr->finalizerCmdNamePtr) + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + return JIM_OK; +} + +int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * References Garbage Collection + * ---------------------------------------------------------------------------*/ + +/* This the hash table type for the "MARK" phase of the GC */ +static const Jim_HashTableType JimRefMarkHashTableType = { + JimReferencesHTHashFunction, /* hash function */ + JimReferencesHTKeyDup, /* key dup */ + NULL, /* val dup */ + JimReferencesHTKeyCompare, /* key compare */ + JimReferencesHTKeyDestructor, /* key destructor */ + NULL /* val destructor */ +}; + +/* Performs the garbage collection. */ +int Jim_Collect(Jim_Interp *interp) +{ + int collected = 0; +#ifndef JIM_BOOTSTRAP + Jim_HashTable marks; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *objPtr; + + /* Avoid recursive calls */ + if (interp->lastCollectId == -1) { + /* Jim_Collect() already running. Return just now. */ + return 0; + } + interp->lastCollectId = -1; + + /* Mark all the references found into the 'mark' hash table. + * The references are searched in every live object that + * is of a type that can contain references. */ + Jim_InitHashTable(&marks, &JimRefMarkHashTableType, NULL); + objPtr = interp->liveList; + while (objPtr) { + if (objPtr->typePtr == NULL || objPtr->typePtr->flags & JIM_TYPE_REFERENCES) { + const char *str, *p; + int len; + + /* If the object is of type reference, to get the + * Id is simple... */ + if (objPtr->typePtr == &referenceObjType) { + Jim_AddHashEntry(&marks, &objPtr->internalRep.refValue.id, NULL); +#ifdef JIM_DEBUG_GC + printf("MARK (reference): %d refcount: %d" JIM_NL, + (int)objPtr->internalRep.refValue.id, objPtr->refCount); +#endif + objPtr = objPtr->nextObjPtr; + continue; + } + /* Get the string repr of the object we want + * to scan for references. */ + p = str = Jim_GetString(objPtr, &len); + /* Skip objects too little to contain references. */ + if (len < JIM_REFERENCE_SPACE) { + objPtr = objPtr->nextObjPtr; + continue; + } + /* Extract references from the object string repr. */ + while (1) { + int i; + jim_wide id; + char buf[21]; + + if ((p = strstr(p, "<reference.<")) == NULL) + break; + /* Check if it's a valid reference. */ + if (len - (p - str) < JIM_REFERENCE_SPACE) + break; + if (p[41] != '>' || p[19] != '>' || p[20] != '.') + break; + for (i = 21; i <= 40; i++) + if (!isdigit(UCHAR(p[i]))) + break; + /* Get the ID */ + memcpy(buf, p + 21, 20); + buf[20] = '\0'; + Jim_StringToWide(buf, &id, 10); + + /* Ok, a reference for the given ID + * was found. Mark it. */ + Jim_AddHashEntry(&marks, &id, NULL); +#ifdef JIM_DEBUG_GC + printf("MARK: %d" JIM_NL, (int)id); +#endif + p += JIM_REFERENCE_SPACE; + } + } + objPtr = objPtr->nextObjPtr; + } + + /* Run the references hash table to destroy every reference that + * is not referenced outside (not present in the mark HT). */ + htiter = Jim_GetHashTableIterator(&interp->references); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + const jim_wide *refId; + Jim_Reference *refPtr; + + refId = he->key; + /* Check if in the mark phase we encountered + * this reference. */ + if (Jim_FindHashEntry(&marks, refId) == NULL) { +#ifdef JIM_DEBUG_GC + printf("COLLECTING %d" JIM_NL, (int)*refId); +#endif + collected++; + /* Drop the reference, but call the + * finalizer first if registered. */ + refPtr = he->u.val; + if (refPtr->finalizerCmdNamePtr) { + char *refstr = Jim_Alloc(JIM_REFERENCE_SPACE + 1); + Jim_Obj *objv[3], *oldResult; + + JimFormatReference(refstr, refPtr, *refId); + + objv[0] = refPtr->finalizerCmdNamePtr; + objv[1] = Jim_NewStringObjNoAlloc(interp, refstr, 32); + objv[2] = refPtr->objPtr; + Jim_IncrRefCount(objv[0]); + Jim_IncrRefCount(objv[1]); + Jim_IncrRefCount(objv[2]); + + /* Drop the reference itself */ + Jim_DeleteHashEntry(&interp->references, refId); + + /* Call the finalizer. Errors ignored. */ + oldResult = interp->result; + Jim_IncrRefCount(oldResult); + Jim_EvalObjVector(interp, 3, objv); + Jim_SetResult(interp, oldResult); + Jim_DecrRefCount(interp, oldResult); + + Jim_DecrRefCount(interp, objv[0]); + Jim_DecrRefCount(interp, objv[1]); + Jim_DecrRefCount(interp, objv[2]); + } + else { + Jim_DeleteHashEntry(&interp->references, refId); + } + } + } + Jim_FreeHashTableIterator(htiter); + Jim_FreeHashTable(&marks); + interp->lastCollectId = interp->referenceNextId; + interp->lastCollectTime = time(NULL); +#endif /* JIM_BOOTSTRAP */ + return collected; +} + +#define JIM_COLLECT_ID_PERIOD 5000 +#define JIM_COLLECT_TIME_PERIOD 300 + +void Jim_CollectIfNeeded(Jim_Interp *interp) +{ + jim_wide elapsedId; + int elapsedTime; + + elapsedId = interp->referenceNextId - interp->lastCollectId; + elapsedTime = time(NULL) - interp->lastCollectTime; + + + if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { + Jim_Collect(interp); + } +} +#endif + +static int JimIsBigEndian(void) +{ + union { + unsigned short s; + unsigned char c[2]; + } uval = {0x0102}; + + return uval.c[0] == 1; +} + +/* ----------------------------------------------------------------------------- + * Interpreter related functions + * ---------------------------------------------------------------------------*/ + +Jim_Interp *Jim_CreateInterp(void) +{ + Jim_Interp *i = Jim_Alloc(sizeof(*i)); + + memset(i, 0, sizeof(*i)); + + i->maxNestingDepth = JIM_MAX_NESTING_DEPTH; + i->lastCollectTime = time(NULL); + + /* Note that we can create objects only after the + * interpreter liveList and freeList pointers are + * initialized to NULL. */ + Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i); +#ifdef JIM_REFERENCES + Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); +#endif + Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); + Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL); + i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL); + i->emptyObj = Jim_NewEmptyStringObj(i); + i->trueObj = Jim_NewIntObj(i, 1); + i->falseObj = Jim_NewIntObj(i, 0); + i->errorFileNameObj = i->emptyObj; + i->result = i->emptyObj; + i->stackTrace = Jim_NewListObj(i, NULL, 0); + i->unknown = Jim_NewStringObj(i, "unknown", -1); + i->errorProc = i->emptyObj; + i->currentScriptObj = Jim_NewEmptyStringObj(i); + Jim_IncrRefCount(i->emptyObj); + Jim_IncrRefCount(i->errorFileNameObj); + Jim_IncrRefCount(i->result); + Jim_IncrRefCount(i->stackTrace); + Jim_IncrRefCount(i->unknown); + Jim_IncrRefCount(i->currentScriptObj); + Jim_IncrRefCount(i->errorProc); + Jim_IncrRefCount(i->trueObj); + Jim_IncrRefCount(i->falseObj); + + /* Initialize key variables every interpreter should contain */ + Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); + Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); + + Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); + Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); + Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); + Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", JimIsBigEndian() ? "bigEndian" : "littleEndian"); + Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); + Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); + Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); + + return i; +} + +void Jim_FreeInterp(Jim_Interp *i) +{ + Jim_CallFrame *cf = i->framePtr, *prevcf, *nextcf; + Jim_Obj *objPtr, *nextObjPtr; + + Jim_DecrRefCount(i, i->emptyObj); + Jim_DecrRefCount(i, i->trueObj); + Jim_DecrRefCount(i, i->falseObj); + Jim_DecrRefCount(i, i->result); + Jim_DecrRefCount(i, i->stackTrace); + Jim_DecrRefCount(i, i->errorProc); + Jim_DecrRefCount(i, i->unknown); + Jim_DecrRefCount(i, i->errorFileNameObj); + Jim_DecrRefCount(i, i->currentScriptObj); + Jim_FreeHashTable(&i->commands); +#ifdef JIM_REFERENCES + Jim_FreeHashTable(&i->references); +#endif + Jim_FreeHashTable(&i->packages); + Jim_Free(i->prngState); + Jim_FreeHashTable(&i->assocData); + JimDeleteLocalProcs(i); + + /* Free the call frames list */ + while (cf) { + prevcf = cf->parentCallFrame; + JimFreeCallFrame(i, cf, JIM_FCF_NONE); + cf = prevcf; + } + /* Check that the live object list is empty, otherwise + * there is a memory leak. */ + if (i->liveList != NULL) { + objPtr = i->liveList; + + printf(JIM_NL "-------------------------------------" JIM_NL); + printf("Objects still in the free list:" JIM_NL); + while (objPtr) { + const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; + + printf("%p (%d) %-10s: '%.20s'" JIM_NL, + (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); + if (objPtr->typePtr == &sourceObjType) { + printf("FILE %s LINE %d" JIM_NL, + Jim_String(objPtr->internalRep.sourceValue.fileNameObj), + objPtr->internalRep.sourceValue.lineNumber); + } + objPtr = objPtr->nextObjPtr; + } + printf("-------------------------------------" JIM_NL JIM_NL); + JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); + } + /* Free all the freed objects. */ + objPtr = i->freeList; + while (objPtr) { + nextObjPtr = objPtr->nextObjPtr; + Jim_Free(objPtr); + objPtr = nextObjPtr; + } + /* Free cached CallFrame structures */ + cf = i->freeFramesList; + while (cf) { + nextcf = cf->nextFramePtr; + if (cf->vars.table != NULL) + Jim_Free(cf->vars.table); + Jim_Free(cf); + cf = nextcf; + } +#ifdef jim_ext_load + Jim_FreeLoadHandles(i); +#endif + + /* Free the interpreter structure. */ + Jim_Free(i); +} + +/* Returns the call frame relative to the level represented by + * levelObjPtr. If levelObjPtr == NULL, the * level is assumed to be '1'. + * + * This function accepts the 'level' argument in the form + * of the commands [uplevel] and [upvar]. + * + * For a function accepting a relative integer as level suitable + * for implementation of [info level ?level?] check the + * JimGetCallFrameByInteger() function. + * + * Returns NULL on error. + */ +Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + const char *str; + Jim_CallFrame *framePtr; + + if (levelObjPtr) { + str = Jim_String(levelObjPtr); + if (str[0] == '#') { + char *endptr; + + level = strtol(str + 1, &endptr, 0); + if (str[1] == '\0' || endptr[0] != '\0') { + level = -1; + } + } + else { + if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { + level = -1; + } + else { + /* Convert from a relative to an absolute level */ + level = interp->framePtr->level - level; + } + } + } + else { + str = "1"; /* Needed to format the error message. */ + level = interp->framePtr->level - 1; + } + + if (level == 0) { + return interp->topFramePtr; + } + if (level > 0) { + /* Lookup */ + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%s\"", str); + return NULL; +} + +/* Similar to Jim_GetCallFrameByLevel() but the level is specified + * as a relative integer like in the [info level ?level?] command. + **/ +static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + Jim_CallFrame *framePtr; + + if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { + if (level <= 0) { + /* Convert from a relative to an absolute level */ + level = interp->framePtr->level + level; + } + + if (level == 0) { + return interp->topFramePtr; + } + + /* Lookup */ + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parentCallFrame) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return NULL; +} + +static void JimResetStackTrace(Jim_Interp *interp) +{ + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(interp->stackTrace); +} + +static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) +{ + int len; + + /* Increment reference first in case these are the same object */ + Jim_IncrRefCount(stackTraceObj); + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = stackTraceObj; + interp->errorFlag = 1; + + /* This is a bit ugly. + * If the filename of the last entry of the stack trace is empty, + * the next stack level should be added. + */ + len = Jim_ListLength(interp, interp->stackTrace); + if (len >= 3) { + Jim_Obj *filenameObj; + + Jim_ListIndex(interp, interp->stackTrace, len - 2, &filenameObj, JIM_NONE); + + Jim_GetString(filenameObj, &len); + + if (!Jim_Length(filenameObj)) { + interp->addStackTrace = 1; + } + } +} + +/* Returns 1 if the stack trace information was used or 0 if not */ +static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, + Jim_Obj *fileNameObj, int linenr) +{ + if (strcmp(procname, "unknown") == 0) { + procname = ""; + } + if (!*procname && !Jim_Length(fileNameObj)) { + /* No useful info here */ + return; + } + + if (Jim_IsShared(interp->stackTrace)) { + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); + Jim_IncrRefCount(interp->stackTrace); + } + + /* If we have no procname but the previous element did, merge with that frame */ + if (!*procname && Jim_Length(fileNameObj)) { + /* Just a filename. Check the previous entry */ + int len = Jim_ListLength(interp, interp->stackTrace); + + if (len >= 3) { + Jim_Obj *objPtr; + if (Jim_ListIndex(interp, interp->stackTrace, len - 3, &objPtr, JIM_NONE) == JIM_OK && Jim_Length(objPtr)) { + /* Yes, the previous level had procname */ + if (Jim_ListIndex(interp, interp->stackTrace, len - 2, &objPtr, JIM_NONE) == JIM_OK && !Jim_Length(objPtr)) { + /* But no filename, so merge the new info with that frame */ + ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); + ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); + return; + } + } + } + } + + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1)); + Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj); + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr)); +} + +int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc, + void *data) +{ + AssocDataValue *assocEntryPtr = (AssocDataValue *) Jim_Alloc(sizeof(AssocDataValue)); + + assocEntryPtr->delProc = delProc; + assocEntryPtr->data = data; + return Jim_AddHashEntry(&interp->assocData, key, assocEntryPtr); +} + +void *Jim_GetAssocData(Jim_Interp *interp, const char *key) +{ + Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); + + if (entryPtr != NULL) { + AssocDataValue *assocEntryPtr = (AssocDataValue *) entryPtr->u.val; + + return assocEntryPtr->data; + } + return NULL; +} + +int Jim_DeleteAssocData(Jim_Interp *interp, const char *key) +{ + return Jim_DeleteHashEntry(&interp->assocData, key); +} + +int Jim_GetExitCode(Jim_Interp *interp) +{ + return interp->exitCode; +} + +/* ----------------------------------------------------------------------------- + * Integer object + * ---------------------------------------------------------------------------*/ +#define JIM_INTEGER_SPACE 24 + +static void UpdateStringOfInt(struct Jim_Obj *objPtr); +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); + +static const Jim_ObjType intObjType = { + "int", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + +/* A coerced double is closer to an int than a double. + * It is an int value temporarily masquerading as a double value. + * i.e. it has the same string value as an int and Jim_GetWide() + * succeeds, but also Jim_GetDouble() returns the value directly. + */ +static const Jim_ObjType coercedDoubleObjType = { + "coerced-double", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + + +void UpdateStringOfInt(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_INTEGER_SPACE + 1]; + + len = Jim_WideToString(buf, JimWideValue(objPtr)); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + jim_wide wideValue; + const char *str; + + if (objPtr->typePtr == &coercedDoubleObjType) { + /* Simple switcheroo */ + objPtr->typePtr = &intObjType; + return JIM_OK; + } + + /* Get the string representation */ + str = Jim_String(objPtr); + /* Try to convert into a jim_wide */ + if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); + } + return JIM_ERR; + } + if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { + Jim_SetResultString(interp, "Integer value too big to be represented", -1); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &intObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; +} + +#ifdef JIM_OPTIMIZATION +static int JimIsWide(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &intObjType; +} +#endif + +int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + +/* Get a wide but does not set an error if the format is bad. */ +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + +int Jim_GetLong(Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr) +{ + jim_wide wideValue; + int retval; + + retval = Jim_GetWide(interp, objPtr, &wideValue); + if (retval == JIM_OK) { + *longPtr = (long)wideValue; + return JIM_OK; + } + return JIM_ERR; +} + +Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &intObjType; + objPtr->bytes = NULL; + objPtr->internalRep.wideValue = wideValue; + return objPtr; +} + +/* ----------------------------------------------------------------------------- + * Double object + * ---------------------------------------------------------------------------*/ +#define JIM_DOUBLE_SPACE 30 + +static void UpdateStringOfDouble(struct Jim_Obj *objPtr); +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr); + +static const Jim_ObjType doubleObjType = { + "double", + NULL, + NULL, + UpdateStringOfDouble, + JIM_TYPE_NONE, +}; + +void UpdateStringOfDouble(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_DOUBLE_SPACE + 1]; + + len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue); + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + double doubleValue; + jim_wide wideValue; + const char *str; + + /* Preserve the string representation. + * Needed so we can convert back to int without loss + */ + str = Jim_String(objPtr); + +#ifdef HAVE_LONG_LONG + /* Assume a 53 bit mantissa */ +#define MIN_INT_IN_DOUBLE -(1LL << 53) +#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) + + if (objPtr->typePtr == &intObjType + && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE + && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { + + /* Direct conversion to coerced double */ + objPtr->typePtr = &coercedDoubleObjType; + return JIM_OK; + } + else +#endif + if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { + /* Managed to convert to an int, so we can use this as a cooerced double */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &coercedDoubleObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; + } + else { + /* Try to convert into a double */ + if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected number but got \"%#s\"", objPtr); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + } + objPtr->typePtr = &doubleObjType; + objPtr->internalRep.doubleValue = doubleValue; + return JIM_OK; +} + +int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr) +{ + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + return JIM_OK; + } + if (objPtr->typePtr != &doubleObjType && SetDoubleFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + } + else { + *doublePtr = objPtr->internalRep.doubleValue; + } + return JIM_OK; +} + +Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &doubleObjType; + objPtr->bytes = NULL; + objPtr->internalRep.doubleValue = doubleValue; + return objPtr; +} + +/* ----------------------------------------------------------------------------- + * List object + * ---------------------------------------------------------------------------*/ +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); +static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfList(struct Jim_Obj *objPtr); +static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +/* Note that while the elements of the list may contain references, + * the list object itself can't. This basically means that the + * list object string representation as a whole can't contain references + * that are not presents in the single elements. */ +static const Jim_ObjType listObjType = { + "list", + FreeListInternalRep, + DupListInternalRep, + UpdateStringOfList, + JIM_TYPE_NONE, +}; + +void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + Jim_DecrRefCount(interp, objPtr->internalRep.listValue.ele[i]); + } + Jim_Free(objPtr->internalRep.listValue.ele); +} + +void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + int i; + + JIM_NOTUSED(interp); + + dupPtr->internalRep.listValue.len = srcPtr->internalRep.listValue.len; + dupPtr->internalRep.listValue.maxLen = srcPtr->internalRep.listValue.maxLen; + dupPtr->internalRep.listValue.ele = + Jim_Alloc(sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.maxLen); + memcpy(dupPtr->internalRep.listValue.ele, srcPtr->internalRep.listValue.ele, + sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.len); + for (i = 0; i < dupPtr->internalRep.listValue.len; i++) { + Jim_IncrRefCount(dupPtr->internalRep.listValue.ele[i]); + } + dupPtr->typePtr = &listObjType; +} + +/* The following function checks if a given string can be encoded + * into a list element without any kind of quoting, surrounded by braces, + * or using escapes to quote. */ +#define JIM_ELESTR_SIMPLE 0 +#define JIM_ELESTR_BRACE 1 +#define JIM_ELESTR_QUOTE 2 +static int ListElementQuotingType(const char *s, int len) +{ + int i, level, blevel, trySimple = 1; + + /* Try with the SIMPLE case */ + if (len == 0) + return JIM_ELESTR_BRACE; + if (s[0] == '#') + return JIM_ELESTR_BRACE; + if (s[0] == '"' || s[0] == '{') { + trySimple = 0; + goto testbrace; + } + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + trySimple = 0; + case '{': + case '}': + goto testbrace; + } + } + return JIM_ELESTR_SIMPLE; + + testbrace: + /* Test if it's possible to do with braces */ + if (s[len - 1] == '\\') + return JIM_ELESTR_QUOTE; + level = 0; + blevel = 0; + for (i = 0; i < len; i++) { + switch (s[i]) { + case '{': + level++; + break; + case '}': + level--; + if (level < 0) + return JIM_ELESTR_QUOTE; + break; + case '[': + blevel++; + break; + case ']': + blevel--; + break; + case '\\': + if (s[i + 1] == '\n') + return JIM_ELESTR_QUOTE; + else if (s[i + 1] != '\0') + i++; + break; + } + } + if (blevel < 0) { + return JIM_ELESTR_QUOTE; + } + + if (level == 0) { + if (!trySimple) + return JIM_ELESTR_BRACE; + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + return JIM_ELESTR_BRACE; + break; + } + } + return JIM_ELESTR_SIMPLE; + } + return JIM_ELESTR_QUOTE; +} + +/* Returns the malloc-ed representation of a string + * using backslash to quote special chars. */ +static char *BackslashQuoteString(const char *s, int len, int *qlenPtr) +{ + char *q = Jim_Alloc(len * 2 + 1), *p; + + p = q; + while (*s) { + switch (*s) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case '{': + case '}': + case ';': + case '\\': + *p++ = '\\'; + *p++ = *s++; + break; + case '\n': + *p++ = '\\'; + *p++ = 'n'; + s++; + break; + case '\r': + *p++ = '\\'; + *p++ = 'r'; + s++; + break; + case '\t': + *p++ = '\\'; + *p++ = 't'; + s++; + break; + case '\f': + *p++ = '\\'; + *p++ = 'f'; + s++; + break; + case '\v': + *p++ = '\\'; + *p++ = 'v'; + s++; + break; + default: + *p++ = *s++; + break; + } + } + *p = '\0'; + *qlenPtr = p - q; + return q; +} + +static void UpdateStringOfList(struct Jim_Obj *objPtr) +{ + int i, bufLen, realLength; + const char *strRep; + char *p; + int *quotingType; + Jim_Obj **ele = objPtr->internalRep.listValue.ele; + + /* (Over) Estimate the space needed. */ + quotingType = Jim_Alloc(sizeof(int) * objPtr->internalRep.listValue.len + 1); + bufLen = 0; + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + int len; + + strRep = Jim_GetString(ele[i], &len); + quotingType[i] = ListElementQuotingType(strRep, len); + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + bufLen += len; + break; + case JIM_ELESTR_BRACE: + bufLen += len + 2; + break; + case JIM_ELESTR_QUOTE: + bufLen += len * 2; + break; + } + bufLen++; /* elements separator. */ + } + bufLen++; + + /* Generate the string rep. */ + p = objPtr->bytes = Jim_Alloc(bufLen + 1); + realLength = 0; + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + int len, qlen; + char *q; + + strRep = Jim_GetString(ele[i], &len); + + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + memcpy(p, strRep, len); + p += len; + realLength += len; + break; + case JIM_ELESTR_BRACE: + *p++ = '{'; + memcpy(p, strRep, len); + p += len; + *p++ = '}'; + realLength += len + 2; + break; + case JIM_ELESTR_QUOTE: + q = BackslashQuoteString(strRep, len, &qlen); + memcpy(p, q, qlen); + Jim_Free(q); + p += qlen; + realLength += qlen; + break; + } + /* Add a separating space */ + if (i + 1 != objPtr->internalRep.listValue.len) { + *p++ = ' '; + realLength++; + } + } + *p = '\0'; /* nul term. */ + objPtr->length = realLength; + Jim_Free(quotingType); +} + +int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + struct JimParserCtx parser; + const char *str; + int strLen; + Jim_Obj *fileNameObj; + int linenr; + + /* Try to preserve information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + linenr = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + linenr = 1; + } + Jim_IncrRefCount(fileNameObj); + + /* Get the string representation */ + str = Jim_GetString(objPtr, &strLen); + + /* Free the old internal repr just now and initialize the + * new one just now. The string->list conversion can't fail. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &listObjType; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + objPtr->internalRep.listValue.ele = NULL; + + /* Convert into a list */ + JimParserInit(&parser, str, strLen, linenr); + while (!parser.eof) { + Jim_Obj *elementPtr; + + JimParseList(&parser); + if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC) + continue; + elementPtr = JimParserGetTokenObj(interp, &parser); + JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); + ListAppendElement(objPtr, elementPtr); + } + Jim_DecrRefCount(interp, fileNameObj); + return JIM_OK; +} + +Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + int i; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &listObjType; + objPtr->bytes = NULL; + objPtr->internalRep.listValue.ele = NULL; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + for (i = 0; i < len; i++) { + ListAppendElement(objPtr, elements[i]); + } + return objPtr; +} + +/* Return a vector of Jim_Obj with the elements of a Jim list, and the + * length of the vector. Note that the user of this function should make + * sure that the list object can't shimmer while the vector returned + * is in use, this vector is the one stored inside the internal representation + * of the list object. This function is not exported, extensions should + * always access to the List object elements using Jim_ListIndex(). */ +static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen, + Jim_Obj ***listVec) +{ + *listLen = Jim_ListLength(interp, listObj); + *listVec = listObj->internalRep.listValue.ele; +} + +/* Sorting uses ints, but commands may return wide */ +static int JimSign(jim_wide w) +{ + if (w == 0) { + return 0; + } + else if (w < 0) { + return -1; + } + return 1; +} + +/* ListSortElements type values */ +struct lsort_info { + jmp_buf jmpbuf; + Jim_Obj *command; + Jim_Interp *interp; + enum { + JIM_LSORT_ASCII, + JIM_LSORT_NOCASE, + JIM_LSORT_INTEGER, + JIM_LSORT_COMMAND + } type; + int order; + int index; + int indexed; + int (*subfn)(Jim_Obj **, Jim_Obj **); +}; + +static struct lsort_info *sort_info; + +static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *lObj, *rObj; + + if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK || + Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + return sort_info->subfn(&lObj, &rObj); +} + +/* Sort the internal rep of a list. */ +static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order; +} + +static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order; +} + +static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + jim_wide lhs = 0, rhs = 0; + + if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK || + Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + + return JimSign(lhs - rhs) * sort_info->order; +} + +static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *compare_script; + int rc; + + jim_wide ret = 0; + + /* This must be a valid list */ + compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); + Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); + Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); + + rc = Jim_EvalObj(sort_info->interp, compare_script); + + if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) { + longjmp(sort_info->jmpbuf, rc); + } + + return JimSign(ret) * sort_info->order; +} + +/* Sort a list *in place*. MUST be called with non-shared objects. */ +static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) +{ + struct lsort_info *prev_info; + + typedef int (qsort_comparator) (const void *, const void *); + int (*fn) (Jim_Obj **, Jim_Obj **); + Jim_Obj **vector; + int len; + int rc; + + JimPanic((Jim_IsShared(listObjPtr), "Jim_ListSortElements called with shared object")); + if (!Jim_IsList(listObjPtr)) + SetListFromAny(interp, listObjPtr); + + /* Allow lsort to be called reentrantly */ + prev_info = sort_info; + sort_info = info; + + vector = listObjPtr->internalRep.listValue.ele; + len = listObjPtr->internalRep.listValue.len; + switch (info->type) { + case JIM_LSORT_ASCII: + fn = ListSortString; + break; + case JIM_LSORT_NOCASE: + fn = ListSortStringNoCase; + break; + case JIM_LSORT_INTEGER: + fn = ListSortInteger; + break; + case JIM_LSORT_COMMAND: + fn = ListSortCommand; + break; + default: + fn = NULL; /* avoid warning */ + JimPanic((1, "ListSort called with invalid sort type")); + } + + if (info->indexed) { + /* Need to interpose a "list index" function */ + info->subfn = fn; + fn = ListSortIndexHelper; + } + + if ((rc = setjmp(info->jmpbuf)) == 0) { + qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); + } + Jim_InvalidateStringRep(listObjPtr); + sort_info = prev_info; + + return rc; +} + +/* This is the low-level function to insert elements into a list. + * The higher-level Jim_ListInsertElements() performs shared object + * check and invalidate the string repr. This version is used + * in the internals of the List Object and is not exported. + * + * NOTE: this function can be called only against objects + * with internal type of List. */ +static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec) +{ + int currentLen = listPtr->internalRep.listValue.len; + int requiredLen = currentLen + elemc; + int i; + Jim_Obj **point; + + if (requiredLen > listPtr->internalRep.listValue.maxLen) { + int maxLen = requiredLen * 2; + + listPtr->internalRep.listValue.ele = + Jim_Realloc(listPtr->internalRep.listValue.ele, sizeof(Jim_Obj *) * maxLen); + listPtr->internalRep.listValue.maxLen = maxLen; + } + point = listPtr->internalRep.listValue.ele + idx; + memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *)); + for (i = 0; i < elemc; ++i) { + point[i] = elemVec[i]; + Jim_IncrRefCount(point[i]); + } + listPtr->internalRep.listValue.len += elemc; +} + +/* Convenience call to ListInsertElements() to append a single element. + */ +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + ListInsertElements(listPtr, listPtr->internalRep.listValue.len, 1, &objPtr); +} + + +/* Appends every element of appendListPtr into listPtr. + * Both have to be of the list type. + * Convenience call to ListInsertElements() + */ +static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + ListInsertElements(listPtr, listPtr->internalRep.listValue.len, + appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele); +} + +void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendElement(listPtr, objPtr); +} + +void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendList(listPtr, appendListPtr); +} + +int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (!Jim_IsList(objPtr)) + SetListFromAny(interp, objPtr); + return objPtr->internalRep.listValue.len; +} + +void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + int objc, Jim_Obj *const *objVec) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object")); + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if (idx >= 0 && idx > listPtr->internalRep.listValue.len) + idx = listPtr->internalRep.listValue.len; + else if (idx < 0) + idx = 0; + Jim_InvalidateStringRep(listPtr); + ListInsertElements(listPtr, idx, objc, objVec); +} + +int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags) +{ + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + *objPtrPtr = NULL; + return JIM_ERR; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + *objPtrPtr = listPtr->internalRep.listValue.ele[idx]; + return JIM_OK; +} + +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + Jim_Obj *newObjPtr, int flags) +{ + if (!Jim_IsList(listPtr)) + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + return JIM_ERR; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]); + listPtr->internalRep.listValue.ele[idx] = newObjPtr; + Jim_IncrRefCount(newObjPtr); + return JIM_OK; +} + +/* Modify the list stored into the variable named 'varNamePtr' + * setting the element specified by the 'indexc' indexes objects in 'indexv', + * with the new element 'newObjptr'. */ +int Jim_SetListIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) +{ + Jim_Obj *varObjPtr, *objPtr, *listObjPtr; + int shared, i, idx; + + varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED); + if (objPtr == NULL) + return JIM_ERR; + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < indexc - 1; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK) + goto err; + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) { + goto err; + } + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE); + } + Jim_InvalidateStringRep(listObjPtr); + } + if (Jim_GetIndex(interp, indexv[indexc - 1], &idx) != JIM_OK) + goto err; + if (ListSetIndex(interp, objPtr, idx, newObjPtr, JIM_ERRMSG) == JIM_ERR) + goto err; + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) + goto err; + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + int i; + + /* If all the objects in objv are lists, + * it's possible to return a list as result, that's the + * concatenation of all the lists. */ + for (i = 0; i < objc; i++) { + if (!Jim_IsList(objv[i])) + break; + } + if (i == objc) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < objc; i++) + Jim_ListAppendList(interp, objPtr, objv[i]); + return objPtr; + } + else { + /* Else... we have to glue strings together */ + int len = 0, objLen; + char *bytes, *p; + + /* Compute the length */ + for (i = 0; i < objc; i++) { + Jim_GetString(objv[i], &objLen); + len += objLen; + } + if (objc) + len += objc - 1; + /* Create the string rep, and a string object holding it. */ + p = bytes = Jim_Alloc(len + 1); + for (i = 0; i < objc; i++) { + const char *s = Jim_GetString(objv[i], &objLen); + + /* Remove leading space */ + while (objLen && (*s == ' ' || *s == '\t' || *s == '\n')) { + s++; + objLen--; + len--; + } + /* And trailing space */ + while (objLen && (s[objLen - 1] == ' ' || + s[objLen - 1] == '\n' || s[objLen - 1] == '\t')) { + /* Handle trailing backslash-space case */ + if (objLen > 1 && s[objLen - 2] == '\\') { + break; + } + objLen--; + len--; + } + memcpy(p, s, objLen); + p += objLen; + if (objLen && i + 1 != objc) { + *p++ = ' '; + } + else if (i + 1 != objc) { + /* Drop the space calcuated for this + * element that is instead null. */ + len--; + } + } + *p = '\0'; + return Jim_NewStringObjNoAlloc(interp, bytes, len); + } +} + +/* Returns a list composed of the elements in the specified range. + * first and start are directly accepted as Jim_Objects and + * processed for the end?-index? case. */ +Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr) +{ + int first, last; + int len, rangeLen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + len = Jim_ListLength(interp, listObjPtr); /* will convert into list */ + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + if (first == 0 && last == len) { + return listObjPtr; + } + return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen); +} + +/* ----------------------------------------------------------------------------- + * Dict object + * ---------------------------------------------------------------------------*/ +static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfDict(struct Jim_Obj *objPtr); +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +/* Dict HashTable Type. + * + * Keys and Values are Jim objects. */ + +static unsigned int JimObjectHTHashFunction(const void *key) +{ + const char *str; + Jim_Obj *objPtr = (Jim_Obj *)key; + int len; + + str = Jim_GetString(objPtr, &len); + return Jim_GenHashFunction((unsigned char *)str, len); +} + +static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); +} + +static void JimObjectHTKeyValDestructor(void *interp, void *val) +{ + Jim_Obj *objPtr = val; + + Jim_DecrRefCount(interp, objPtr); +} + +static const Jim_HashTableType JimDictHashTableType = { + JimObjectHTHashFunction, /* hash function */ + NULL, /* key dup */ + NULL, /* val dup */ + JimObjectHTKeyCompare, /* key compare */ + (void (*)(void *, const void *)) /* ATTENTION: const cast */ + JimObjectHTKeyValDestructor, /* key destructor */ + JimObjectHTKeyValDestructor /* val destructor */ +}; + +/* Note that while the elements of the dict may contain references, + * the list object itself can't. This basically means that the + * dict object string representation as a whole can't contain references + * that are not presents in the single elements. */ +static const Jim_ObjType dictObjType = { + "dict", + FreeDictInternalRep, + DupDictInternalRep, + UpdateStringOfDict, + JIM_TYPE_NONE, +}; + +void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + + Jim_FreeHashTable(objPtr->internalRep.ptr); + Jim_Free(objPtr->internalRep.ptr); +} + +void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + Jim_HashTable *ht, *dupHt; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + + /* Create a new hash table */ + ht = srcPtr->internalRep.ptr; + dupHt = Jim_Alloc(sizeof(*dupHt)); + Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); + if (ht->size != 0) + Jim_ExpandHashTable(dupHt, ht->size); + /* Copy every element from the source to the dup hash table */ + htiter = Jim_GetHashTableIterator(ht); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + const Jim_Obj *keyObjPtr = he->key; + Jim_Obj *valObjPtr = he->u.val; + + Jim_IncrRefCount((Jim_Obj *)keyObjPtr); /* ATTENTION: const cast */ + Jim_IncrRefCount(valObjPtr); + Jim_AddHashEntry(dupHt, keyObjPtr, valObjPtr); + } + Jim_FreeHashTableIterator(htiter); + + dupPtr->internalRep.ptr = dupHt; + dupPtr->typePtr = &dictObjType; +} + +void UpdateStringOfDict(struct Jim_Obj *objPtr) +{ + int i, bufLen, realLength; + const char *strRep; + char *p; + int *quotingType, objc; + Jim_HashTable *ht; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj **objv; + + /* Trun the hash table into a flat vector of Jim_Objects. */ + ht = objPtr->internalRep.ptr; + objc = ht->used * 2; + objv = Jim_Alloc(objc * sizeof(Jim_Obj *)); + htiter = Jim_GetHashTableIterator(ht); + i = 0; + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */ + objv[i++] = he->u.val; + } + Jim_FreeHashTableIterator(htiter); + /* (Over) Estimate the space needed. */ + quotingType = Jim_Alloc(sizeof(int) * objc); + bufLen = 0; + for (i = 0; i < objc; i++) { + int len; + + strRep = Jim_GetString(objv[i], &len); + quotingType[i] = ListElementQuotingType(strRep, len); + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + bufLen += len; + break; + case JIM_ELESTR_BRACE: + bufLen += len + 2; + break; + case JIM_ELESTR_QUOTE: + bufLen += len * 2; + break; + } + bufLen++; /* elements separator. */ + } + bufLen++; + + /* Generate the string rep. */ + p = objPtr->bytes = Jim_Alloc(bufLen + 1); + realLength = 0; + for (i = 0; i < objc; i++) { + int len, qlen; + char *q; + + strRep = Jim_GetString(objv[i], &len); + + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + memcpy(p, strRep, len); + p += len; + realLength += len; + break; + case JIM_ELESTR_BRACE: + *p++ = '{'; + memcpy(p, strRep, len); + p += len; + *p++ = '}'; + realLength += len + 2; + break; + case JIM_ELESTR_QUOTE: + q = BackslashQuoteString(strRep, len, &qlen); + memcpy(p, q, qlen); + Jim_Free(q); + p += qlen; + realLength += qlen; + break; + } + /* Add a separating space */ + if (i + 1 != objc) { + *p++ = ' '; + realLength++; + } + } + *p = '\0'; /* nul term. */ + objPtr->length = realLength; + Jim_Free(quotingType); + Jim_Free(objv); +} + +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int listlen; + + /* Get the string representation. Do this first so we don't + * change order in case of fast conversion to dict. + */ + Jim_String(objPtr); + + /* For simplicity, convert a non-list object to a list and then to a dict */ + listlen = Jim_ListLength(interp, objPtr); + if (listlen % 2) { + Jim_SetResultString(interp, + "invalid dictionary value: must be a list with an even number of elements", -1); + return JIM_ERR; + } + else { + /* Now it is easy to convert to a dict from a list, and it can't fail */ + Jim_HashTable *ht; + int i; + + ht = Jim_Alloc(sizeof(*ht)); + Jim_InitHashTable(ht, &JimDictHashTableType, interp); + + for (i = 0; i < listlen; i += 2) { + Jim_Obj *keyObjPtr; + Jim_Obj *valObjPtr; + + Jim_ListIndex(interp, objPtr, i, &keyObjPtr, JIM_NONE); + Jim_ListIndex(interp, objPtr, i + 1, &valObjPtr, JIM_NONE); + + Jim_IncrRefCount(keyObjPtr); + Jim_IncrRefCount(valObjPtr); + + if (Jim_AddHashEntry(ht, keyObjPtr, valObjPtr) != JIM_OK) { + Jim_HashEntry *he; + + he = Jim_FindHashEntry(ht, keyObjPtr); + Jim_DecrRefCount(interp, keyObjPtr); + /* ATTENTION: const cast */ + Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); + he->u.val = valObjPtr; + } + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictObjType; + objPtr->internalRep.ptr = ht; + + return JIM_OK; + } +} + +/* Dict object API */ + +/* Add an element to a dict. objPtr must be of the "dict" type. + * The higer-level exported function is Jim_DictAddElement(). + * If an element with the specified key already exists, the value + * associated is replaced with the new one. + * + * if valueObjPtr == NULL, the key is instead removed if it exists. */ +static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + Jim_HashTable *ht = objPtr->internalRep.ptr; + + if (valueObjPtr == NULL) { /* unset */ + return Jim_DeleteHashEntry(ht, keyObjPtr); + } + Jim_IncrRefCount(keyObjPtr); + Jim_IncrRefCount(valueObjPtr); + if (Jim_AddHashEntry(ht, keyObjPtr, valueObjPtr) != JIM_OK) { + Jim_HashEntry *he = Jim_FindHashEntry(ht, keyObjPtr); + + Jim_DecrRefCount(interp, keyObjPtr); + /* ATTENTION: const cast */ + Jim_DecrRefCount(interp, (Jim_Obj *)he->u.val); + he->u.val = valueObjPtr; + } + return JIM_OK; +} + +/* Add an element, higher-level interface for DictAddElement(). + * If valueObjPtr == NULL, the key is removed if it exists. */ +int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + int retcode; + + JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); + if (objPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, objPtr) != JIM_OK) + return JIM_ERR; + } + retcode = DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); + Jim_InvalidateStringRep(objPtr); + return retcode; +} + +Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + int i; + + JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even")); + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &dictObjType; + objPtr->bytes = NULL; + objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp); + for (i = 0; i < len; i += 2) + DictAddElement(interp, objPtr, elements[i], elements[i + 1]); + return objPtr; +} + +/* Return the value associated to the specified dict key + * Note: Returns JIM_OK if OK, JIM_ERR if entry not found or -1 if can't create dict value + */ +int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, + Jim_Obj **objPtrPtr, int flags) +{ + Jim_HashEntry *he; + Jim_HashTable *ht; + + if (dictPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictPtr) != JIM_OK) + return -1; + } + ht = dictPtr->internalRep.ptr; + if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "key \"%#s\" not found in dictionary", keyPtr); + } + return JIM_ERR; + } + *objPtrPtr = he->u.val; + return JIM_OK; +} + +/* Return an allocated array of key/value pairs for the dictionary. Stores the length in *len */ +int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) +{ + Jim_HashTable *ht; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj **objv; + int i; + + if (dictPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictPtr) != JIM_OK) + return JIM_ERR; + } + ht = dictPtr->internalRep.ptr; + + /* Turn the hash table into a flat vector of Jim_Objects. */ + objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); + htiter = Jim_GetHashTableIterator(ht); + i = 0; + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + objv[i++] = (Jim_Obj *)he->key; /* ATTENTION: const cast */ + objv[i++] = he->u.val; + } + *len = i; + Jim_FreeHashTableIterator(htiter); + *objPtrPtr = objv; + return JIM_OK; +} + + +/* Return the value associated to the specified dict keys */ +int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags) +{ + int i; + + if (keyc == 0) { + *objPtrPtr = dictPtr; + return JIM_OK; + } + + for (i = 0; i < keyc; i++) { + Jim_Obj *objPtr; + + if (Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags) + != JIM_OK) + return JIM_ERR; + dictPtr = objPtr; + } + *objPtrPtr = dictPtr; + return JIM_OK; +} + +/* Modify the dict stored into the variable named 'varNamePtr' + * setting the element specified by the 'keyc' keys objects in 'keyv', + * with the new value of the element 'newObjPtr'. + * + * If newObjPtr == NULL the operation is to remove the given key + * from the dictionary. + * + * If flags & JIM_ERRMSG, then failure to remove the key is considered an error + * and JIM_ERR is returned. Otherwise it is ignored and JIM_OK is returned. + */ +int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags) +{ + Jim_Obj *varObjPtr, *objPtr, *dictObjPtr; + int shared, i; + + varObjPtr = objPtr = + Jim_GetVariable(interp, varNamePtr, newObjPtr == NULL ? JIM_ERRMSG : JIM_NONE); + if (objPtr == NULL) { + if (newObjPtr == NULL) /* Cannot remove a key from non existing var */ { + return JIM_ERR; + } + varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); + if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, varObjPtr); + return JIM_ERR; + } + } + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < keyc - 1; i++) { + dictObjPtr = objPtr; + + /* Check if it's a valid dictionary */ + if (dictObjPtr->typePtr != &dictObjType) { + if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { + goto err; + } + } + /* Check if the given key exists. */ + Jim_InvalidateStringRep(dictObjPtr); + if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, + newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { + /* This key exists at the current level. + * Make sure it's not shared!. */ + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + else { + /* Key not found. If it's an [unset] operation + * this is an error. Only the last key may not + * exist. */ + if (newObjPtr == NULL) { + goto err; + } + /* Otherwise set an empty dictionary + * as key's value. */ + objPtr = Jim_NewDictObj(interp, NULL, 0); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + /* Note error on unset with missing last key is OK */ + if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { + if (newObjPtr || (flags & JIM_ERRMSG)) { + goto err; + } + } + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { + goto err; + } + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +/* ----------------------------------------------------------------------------- + * Index object + * ---------------------------------------------------------------------------*/ +static void UpdateStringOfIndex(struct Jim_Obj *objPtr); +static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType indexObjType = { + "index", + NULL, + NULL, + UpdateStringOfIndex, + JIM_TYPE_NONE, +}; + +void UpdateStringOfIndex(struct Jim_Obj *objPtr) +{ + int len; + char buf[JIM_INTEGER_SPACE + 1]; + + if (objPtr->internalRep.indexValue >= 0) + len = sprintf(buf, "%d", objPtr->internalRep.indexValue); + else if (objPtr->internalRep.indexValue == -1) + len = sprintf(buf, "end"); + else { + len = sprintf(buf, "end%d", objPtr->internalRep.indexValue + 1); + } + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, buf, len + 1); + objPtr->length = len; +} + +int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int idx, end = 0; + const char *str; + char *endptr; + + /* Get the string representation */ + str = Jim_String(objPtr); + + /* Try to convert into an index */ + if (strncmp(str, "end", 3) == 0) { + end = 1; + str += 3; + idx = 0; + } + else { + idx = strtol(str, &endptr, 10); + + if (endptr == str) { + goto badindex; + } + str = endptr; + } + + /* Now str may include or +<num> or -<num> */ + if (*str == '+' || *str == '-') { + int sign = (*str == '+' ? 1 : -1); + + idx += sign * strtol(++str, &endptr, 10); + if (str == endptr || *endptr) { + goto badindex; + } + str = endptr; + } + /* The only thing left should be spaces */ + while (isspace(UCHAR(*str))) { + str++; + } + if (*str) { + goto badindex; + } + if (end) { + if (idx > 0) { + idx = INT_MAX; + } + else { + /* end-1 is repesented as -2 */ + idx--; + } + } + else if (idx < 0) { + idx = -INT_MAX; + } + + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &indexObjType; + objPtr->internalRep.indexValue = idx; + return JIM_OK; + + badindex: + Jim_SetResultFormatted(interp, + "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr); + return JIM_ERR; +} + +int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) +{ + /* Avoid shimmering if the object is an integer. */ + if (objPtr->typePtr == &intObjType) { + jim_wide val = JimWideValue(objPtr); + + if (!(val < LONG_MIN) && !(val > LONG_MAX)) { + *indexPtr = (val < 0) ? -INT_MAX : (long)val;; + return JIM_OK; + } + } + if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *indexPtr = objPtr->internalRep.indexValue; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Return Code Object. + * ---------------------------------------------------------------------------*/ + +/* NOTE: These must be kept in the same order as JIM_OK, JIM_ERR, ... */ +static const char * const jimReturnCodes[] = { + [JIM_OK] = "ok", + [JIM_ERR] = "error", + [JIM_RETURN] = "return", + [JIM_BREAK] = "break", + [JIM_CONTINUE] = "continue", + [JIM_SIGNAL] = "signal", + [JIM_EXIT] = "exit", + [JIM_EVAL] = "eval", + NULL +}; + +#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) + +static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr); + +static const Jim_ObjType returnCodeObjType = { + "return-code", + NULL, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +/* Converts a (standard) return code to a string. Returns "?" for + * non-standard return codes. + */ +const char *Jim_ReturnCode(int code) +{ + if (code < 0 || code >= (int)jimReturnCodesSize) { + return "?"; + } + else { + return jimReturnCodes[code]; + } +} + +int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int returnCode; + jim_wide wideValue; + + /* Try to convert into an integer */ + if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) + returnCode = (int)wideValue; + else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); + return JIM_ERR; + } + /* Free the old internal repr and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &returnCodeObjType; + objPtr->internalRep.returnCode = returnCode; + return JIM_OK; +} + +int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr) +{ + if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *intPtr = objPtr->internalRep.returnCode; + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Expression Parsing + * ---------------------------------------------------------------------------*/ +static int JimParseExprOperator(struct JimParserCtx *pc); +static int JimParseExprNumber(struct JimParserCtx *pc); +static int JimParseExprIrrational(struct JimParserCtx *pc); + +/* Exrp's Stack machine operators opcodes. */ + +/* Binary operators (numbers) */ +enum +{ + /* Continues on from the JIM_TT_ space */ + /* Operations */ + JIM_EXPROP_MUL = JIM_TT_EXPR_OP, /* 15 */ + JIM_EXPROP_DIV, + JIM_EXPROP_MOD, + JIM_EXPROP_SUB, + JIM_EXPROP_ADD, + JIM_EXPROP_LSHIFT, + JIM_EXPROP_RSHIFT, + JIM_EXPROP_ROTL, + JIM_EXPROP_ROTR, + JIM_EXPROP_LT, + JIM_EXPROP_GT, + JIM_EXPROP_LTE, + JIM_EXPROP_GTE, + JIM_EXPROP_NUMEQ, + JIM_EXPROP_NUMNE, + JIM_EXPROP_BITAND, /* 30 */ + JIM_EXPROP_BITXOR, + JIM_EXPROP_BITOR, + + /* Note must keep these together */ + JIM_EXPROP_LOGICAND, /* 33 */ + JIM_EXPROP_LOGICAND_LEFT, + JIM_EXPROP_LOGICAND_RIGHT, + + /* and these */ + JIM_EXPROP_LOGICOR, /* 36 */ + JIM_EXPROP_LOGICOR_LEFT, + JIM_EXPROP_LOGICOR_RIGHT, + + /* and these */ + /* Ternary operators */ + JIM_EXPROP_TERNARY, /* 39 */ + JIM_EXPROP_TERNARY_LEFT, + JIM_EXPROP_TERNARY_RIGHT, + + /* and these */ + JIM_EXPROP_COLON, /* 42 */ + JIM_EXPROP_COLON_LEFT, + JIM_EXPROP_COLON_RIGHT, + + JIM_EXPROP_POW, /* 45 */ + +/* Binary operators (strings) */ + JIM_EXPROP_STREQ, + JIM_EXPROP_STRNE, + JIM_EXPROP_STRIN, + JIM_EXPROP_STRNI, + +/* Unary operators (numbers) */ + JIM_EXPROP_NOT, + JIM_EXPROP_BITNOT, + JIM_EXPROP_UNARYMINUS, + JIM_EXPROP_UNARYPLUS, + + /* Functions */ + JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_ABS, + JIM_EXPROP_FUNC_DOUBLE, + JIM_EXPROP_FUNC_ROUND, + JIM_EXPROP_FUNC_RAND, + JIM_EXPROP_FUNC_SRAND, + + /* math functions from libm */ + JIM_EXPROP_FUNC_SIN, + JIM_EXPROP_FUNC_COS, + JIM_EXPROP_FUNC_TAN, + JIM_EXPROP_FUNC_ASIN, + JIM_EXPROP_FUNC_ACOS, + JIM_EXPROP_FUNC_ATAN, + JIM_EXPROP_FUNC_SINH, + JIM_EXPROP_FUNC_COSH, + JIM_EXPROP_FUNC_TANH, + JIM_EXPROP_FUNC_CEIL, + JIM_EXPROP_FUNC_FLOOR, + JIM_EXPROP_FUNC_EXP, + JIM_EXPROP_FUNC_LOG, + JIM_EXPROP_FUNC_LOG10, + JIM_EXPROP_FUNC_SQRT, + JIM_EXPROP_FUNC_POW, +}; + +struct JimExprState +{ + Jim_Obj **stack; + int stacklen; + int opcode; + int skip; +}; + +/* Operators table */ +typedef struct Jim_ExprOperator +{ + const char *name; + int precedence; + int arity; + int (*funcop) (Jim_Interp *interp, struct JimExprState * e); + int lazy; +} Jim_ExprOperator; + +static void ExprPush(struct JimExprState *e, Jim_Obj *obj) +{ + Jim_IncrRefCount(obj); + e->stack[e->stacklen++] = obj; +} + +static Jim_Obj *ExprPop(struct JimExprState *e) +{ + return e->stack[--e->stacklen]; +} + +static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 0; + int rc = JIM_OK; + Jim_Obj *A = ExprPop(e); + double dA, dC = 0; + jim_wide wA, wC = 0; + + if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + wC = wA; + break; + case JIM_EXPROP_FUNC_ROUND: + wC = wA; + break; + case JIM_EXPROP_FUNC_DOUBLE: + dC = wA; + intresult = 0; + break; + case JIM_EXPROP_FUNC_ABS: + wC = wA >= 0 ? wA : -wA; + break; + case JIM_EXPROP_UNARYMINUS: + wC = -wA; + break; + case JIM_EXPROP_UNARYPLUS: + wC = wA; + break; + case JIM_EXPROP_NOT: + wC = !wA; + break; + default: + abort(); + } + } + else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + wC = dA; + intresult = 1; + break; + case JIM_EXPROP_FUNC_ROUND: + wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); + intresult = 1; + break; + case JIM_EXPROP_FUNC_DOUBLE: + dC = dA; + break; + case JIM_EXPROP_FUNC_ABS: + dC = dA >= 0 ? dA : -dA; + break; + case JIM_EXPROP_UNARYMINUS: + dC = -dA; + break; + case JIM_EXPROP_UNARYPLUS: + dC = dA; + break; + case JIM_EXPROP_NOT: + wC = !dA; + intresult = 1; + break; + default: + abort(); + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static double JimRandDouble(Jim_Interp *interp) +{ + unsigned long x; + JimRandomBytes(interp, &x, sizeof(x)); + + return (double)x / (unsigned long)~0; +} + +static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + jim_wide wA; + + int rc = Jim_GetWide(interp, A, &wA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_BITNOT: + ExprPush(e, Jim_NewIntObj(interp, ~wA)); + break; + case JIM_EXPROP_FUNC_SRAND: + JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + break; + default: + abort(); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) +{ + JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); + + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + + return JIM_OK; +} + +#ifdef JIM_MATH_FUNCTIONS +static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int rc; + Jim_Obj *A = ExprPop(e); + double dA, dC; + + rc = Jim_GetDouble(interp, A, &dA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_SIN: + dC = sin(dA); + break; + case JIM_EXPROP_FUNC_COS: + dC = cos(dA); + break; + case JIM_EXPROP_FUNC_TAN: + dC = tan(dA); + break; + case JIM_EXPROP_FUNC_ASIN: + dC = asin(dA); + break; + case JIM_EXPROP_FUNC_ACOS: + dC = acos(dA); + break; + case JIM_EXPROP_FUNC_ATAN: + dC = atan(dA); + break; + case JIM_EXPROP_FUNC_SINH: + dC = sinh(dA); + break; + case JIM_EXPROP_FUNC_COSH: + dC = cosh(dA); + break; + case JIM_EXPROP_FUNC_TANH: + dC = tanh(dA); + break; + case JIM_EXPROP_FUNC_CEIL: + dC = ceil(dA); + break; + case JIM_EXPROP_FUNC_FLOOR: + dC = floor(dA); + break; + case JIM_EXPROP_FUNC_EXP: + dC = exp(dA); + break; + case JIM_EXPROP_FUNC_LOG: + dC = log(dA); + break; + case JIM_EXPROP_FUNC_LOG10: + dC = log10(dA); + break; + case JIM_EXPROP_FUNC_SQRT: + dC = sqrt(dA); + break; + default: + abort(); + } + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + + Jim_DecrRefCount(interp, A); + + return rc; +} +#endif + +/* A binary operation on two ints */ +static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + jim_wide wA, wB; + int rc = JIM_ERR; + + if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { + jim_wide wC; + + rc = JIM_OK; + + switch (e->opcode) { + case JIM_EXPROP_LSHIFT: + wC = wA << wB; + break; + case JIM_EXPROP_RSHIFT: + wC = wA >> wB; + break; + case JIM_EXPROP_BITAND: + wC = wA & wB; + break; + case JIM_EXPROP_BITXOR: + wC = wA ^ wB; + break; + case JIM_EXPROP_BITOR: + wC = wA | wB; + break; + case JIM_EXPROP_MOD: + if (wB == 0) { + wC = 0; + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + /* + * From Tcl 8.x + * + * This code is tricky: C doesn't guarantee much + * about the quotient or remainder, but Tcl does. + * The remainder always has the same sign as the + * divisor and a smaller absolute value. + */ + int negative = 0; + + if (wB < 0) { + wB = -wB; + wA = -wA; + negative = 1; + } + wC = wA % wB; + if (wC < 0) { + wC += wB; + } + if (negative) { + wC = -wC; + } + } + break; + case JIM_EXPROP_ROTL: + case JIM_EXPROP_ROTR:{ + /* uint32_t would be better. But not everyone has inttypes.h? */ + unsigned long uA = (unsigned long)wA; + unsigned long uB = (unsigned long)wB; + const unsigned int S = sizeof(unsigned long) * 8; + + /* Shift left by the word size or more is undefined. */ + uB %= S; + + if (e->opcode == JIM_EXPROP_ROTR) { + uB = S - uB; + } + wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); + break; + } + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + + +/* A binary operation on two ints or two doubles (or two strings for some ops) */ +static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 0; + int rc = JIM_OK; + double dA, dB, dC = 0; + jim_wide wA, wB, wC = 0; + + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + if ((A->typePtr != &doubleObjType || A->bytes) && + (B->typePtr != &doubleObjType || B->bytes) && + JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { + + /* Both are ints */ + + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: + wC = JimPowWide(wA, wB); + break; + case JIM_EXPROP_ADD: + wC = wA + wB; + break; + case JIM_EXPROP_SUB: + wC = wA - wB; + break; + case JIM_EXPROP_MUL: + wC = wA * wB; + break; + case JIM_EXPROP_DIV: + if (wB == 0) { + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + /* + * From Tcl 8.x + * + * This code is tricky: C doesn't guarantee much + * about the quotient or remainder, but Tcl does. + * The remainder always has the same sign as the + * divisor and a smaller absolute value. + */ + if (wB < 0) { + wB = -wB; + wA = -wA; + } + wC = wA / wB; + if (wA % wB < 0) { + wC--; + } + } + break; + case JIM_EXPROP_LT: + wC = wA < wB; + break; + case JIM_EXPROP_GT: + wC = wA > wB; + break; + case JIM_EXPROP_LTE: + wC = wA <= wB; + break; + case JIM_EXPROP_GTE: + wC = wA >= wB; + break; + case JIM_EXPROP_NUMEQ: + wC = wA == wB; + break; + case JIM_EXPROP_NUMNE: + wC = wA != wB; + break; + default: + abort(); + } + } + else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: +#ifdef JIM_MATH_FUNCTIONS + dC = pow(dA, dB); +#else + Jim_SetResultString(interp, "unsupported", -1); + rc = JIM_ERR; +#endif + break; + case JIM_EXPROP_ADD: + dC = dA + dB; + break; + case JIM_EXPROP_SUB: + dC = dA - dB; + break; + case JIM_EXPROP_MUL: + dC = dA * dB; + break; + case JIM_EXPROP_DIV: + if (dB == 0) { +#ifdef INFINITY + dC = dA < 0 ? -INFINITY : INFINITY; +#else + dC = (dA < 0 ? -1.0 : 1.0) * strtod("Inf", NULL); +#endif + } + else { + dC = dA / dB; + } + break; + case JIM_EXPROP_LT: + wC = dA < dB; + intresult = 1; + break; + case JIM_EXPROP_GT: + wC = dA > dB; + intresult = 1; + break; + case JIM_EXPROP_LTE: + wC = dA <= dB; + intresult = 1; + break; + case JIM_EXPROP_GTE: + wC = dA >= dB; + intresult = 1; + break; + case JIM_EXPROP_NUMEQ: + wC = dA == dB; + intresult = 1; + break; + case JIM_EXPROP_NUMNE: + wC = dA != dB; + intresult = 1; + break; + default: + abort(); + } + } + else { + /* Handle the string case */ + + /* REVISIT: Could optimise the eq/ne case by checking lengths */ + int i = Jim_StringCompareObj(interp, A, B, 0); + + intresult = 1; + + switch (e->opcode) { + case JIM_EXPROP_LT: + wC = i < 0; + break; + case JIM_EXPROP_GT: + wC = i > 0; + break; + case JIM_EXPROP_LTE: + wC = i <= 0; + break; + case JIM_EXPROP_GTE: + wC = i >= 0; + break; + case JIM_EXPROP_NUMEQ: + wC = i == 0; + break; + case JIM_EXPROP_NUMNE: + wC = i != 0; + break; + default: + rc = JIM_ERR; + break; + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + +static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) +{ + int listlen; + int i; + + listlen = Jim_ListLength(interp, listObjPtr); + for (i = 0; i < listlen; i++) { + Jim_Obj *objPtr; + + Jim_ListIndex(interp, listObjPtr, i, &objPtr, JIM_NONE); + + if (Jim_StringEqObj(objPtr, valObj)) { + return 1; + } + } + return 0; +} + +static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + jim_wide wC; + + switch (e->opcode) { + case JIM_EXPROP_STREQ: + case JIM_EXPROP_STRNE: { + int Alen, Blen; + const char *sA = Jim_GetString(A, &Alen); + const char *sB = Jim_GetString(B, &Blen); + + if (e->opcode == JIM_EXPROP_STREQ) { + wC = (Alen == Blen && memcmp(sA, sB, Alen) == 0); + } + else { + wC = (Alen != Blen || memcmp(sA, sB, Alen) != 0); + } + break; + } + case JIM_EXPROP_STRIN: + wC = JimSearchList(interp, B, A); + break; + case JIM_EXPROP_STRNI: + wC = !JimSearchList(interp, B, A); + break; + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return JIM_OK; +} + +static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) +{ + long l; + double d; + + if (Jim_GetLong(interp, obj, &l) == JIM_OK) { + return l != 0; + } + if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { + return d != 0; + } + return -1; +} + +static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + /* false, so skip RHS opcodes with a 0 result */ + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + /* true so continue */ + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + /* false, so do nothing */ + break; + + case 1: + /* true so skip RHS opcodes with a 1 result */ + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + /* Repush A */ + ExprPush(e, A); + + switch (ExprBool(interp, A)) { + case 0: + /* false, skip RHS opcodes */ + e->skip = JimWideValue(skip); + /* Push a dummy value */ + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + /* true so do nothing */ + break; + + case -1: + /* Invalid */ + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + /* No need to check for A as non-boolean */ + if (ExprBool(interp, A)) { + /* true, so skip RHS opcodes */ + e->skip = JimWideValue(skip); + /* Repush B as the answer */ + ExprPush(e, B); + } + + Jim_DecrRefCount(interp, skip); + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + return JIM_OK; +} + +static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) +{ + return JIM_OK; +} + +enum +{ + LAZY_NONE, + LAZY_OP, + LAZY_LEFT, + LAZY_RIGHT +}; + +/* name - precedence - arity - opcode */ +static const struct Jim_ExprOperator Jim_ExprOperators[] = { + [JIM_EXPROP_FUNC_INT] = {"int", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_DOUBLE] = {"double", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ABS] = {"abs", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ROUND] = {"round", 400, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_RAND] = {"rand", 400, 0, JimExprOpNone, LAZY_NONE}, + [JIM_EXPROP_FUNC_SRAND] = {"srand", 400, 1, JimExprOpIntUnary, LAZY_NONE}, + +#ifdef JIM_MATH_FUNCTIONS + [JIM_EXPROP_FUNC_SIN] = {"sin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_COS] = {"cos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_TAN] = {"tan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ASIN] = {"asin", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ACOS] = {"acos", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_ATAN] = {"atan", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_SINH] = {"sinh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_COSH] = {"cosh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_TANH] = {"tanh", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_CEIL] = {"ceil", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_FLOOR] = {"floor", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_EXP] = {"exp", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_LOG] = {"log", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_LOG10] = {"log10", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_SQRT] = {"sqrt", 400, 1, JimExprOpDoubleUnary, LAZY_NONE}, + [JIM_EXPROP_FUNC_POW] = {"pow", 400, 2, JimExprOpBin, LAZY_NONE}, +#endif + + [JIM_EXPROP_NOT] = {"!", 300, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_BITNOT] = {"~", 300, 1, JimExprOpIntUnary, LAZY_NONE}, + [JIM_EXPROP_UNARYMINUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, + [JIM_EXPROP_UNARYPLUS] = {NULL, 300, 1, JimExprOpNumUnary, LAZY_NONE}, + + [JIM_EXPROP_POW] = {"**", 250, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_MUL] = {"*", 200, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_DIV] = {"/", 200, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_MOD] = {"%", 200, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_SUB] = {"-", 100, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_ADD] = {"+", 100, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_ROTL] = {"<<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_ROTR] = {">>>", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_LSHIFT] = {"<<", 90, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_RSHIFT] = {">>", 90, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_LT] = {"<", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_GT] = {">", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_LTE] = {"<=", 80, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_GTE] = {">=", 80, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_NUMEQ] = {"==", 70, 2, JimExprOpBin, LAZY_NONE}, + [JIM_EXPROP_NUMNE] = {"!=", 70, 2, JimExprOpBin, LAZY_NONE}, + + [JIM_EXPROP_STREQ] = {"eq", 60, 2, JimExprOpStrBin, LAZY_NONE}, + [JIM_EXPROP_STRNE] = {"ne", 60, 2, JimExprOpStrBin, LAZY_NONE}, + + [JIM_EXPROP_STRIN] = {"in", 55, 2, JimExprOpStrBin, LAZY_NONE}, + [JIM_EXPROP_STRNI] = {"ni", 55, 2, JimExprOpStrBin, LAZY_NONE}, + + [JIM_EXPROP_BITAND] = {"&", 50, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_BITXOR] = {"^", 49, 2, JimExprOpIntBin, LAZY_NONE}, + [JIM_EXPROP_BITOR] = {"|", 48, 2, JimExprOpIntBin, LAZY_NONE}, + + [JIM_EXPROP_LOGICAND] = {"&&", 10, 2, NULL, LAZY_OP}, + [JIM_EXPROP_LOGICOR] = {"||", 9, 2, NULL, LAZY_OP}, + + [JIM_EXPROP_TERNARY] = {"?", 5, 2, JimExprOpNull, LAZY_OP}, + [JIM_EXPROP_COLON] = {":", 5, 2, JimExprOpNull, LAZY_OP}, + + /* private operators */ + [JIM_EXPROP_TERNARY_LEFT] = {NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT}, + [JIM_EXPROP_TERNARY_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, + [JIM_EXPROP_COLON_LEFT] = {NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT}, + [JIM_EXPROP_COLON_RIGHT] = {NULL, 5, 2, JimExprOpNull, LAZY_RIGHT}, + [JIM_EXPROP_LOGICAND_LEFT] = {NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT}, + [JIM_EXPROP_LOGICAND_RIGHT] = {NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT}, + [JIM_EXPROP_LOGICOR_LEFT] = {NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT}, + [JIM_EXPROP_LOGICOR_RIGHT] = {NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT}, +}; + +#define JIM_EXPR_OPERATORS_NUM \ + (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) + +static int JimParseExpression(struct JimParserCtx *pc) +{ + /* Discard spaces and quoted newline */ + while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + + if (pc->len == 0) { + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '(': + pc->tt = JIM_TT_SUBEXPR_START; + goto singlechar; + case ')': + pc->tt = JIM_TT_SUBEXPR_END; + goto singlechar; + case ',': + pc->tt = JIM_TT_SUBEXPR_COMMA; +singlechar: + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->p++; + pc->len--; + break; + case '[': + return JimParseCmd(pc); + case '$': + if (JimParseVar(pc) == JIM_ERR) + return JimParseExprOperator(pc); + else { + /* Don't allow expr sugar in expressions */ + if (pc->tt == JIM_TT_EXPRSUGAR) { + return JIM_ERR; + } + return JIM_OK; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + return JimParseExprNumber(pc); + case '"': + return JimParseQuote(pc); + case '{': + return JimParseBrace(pc); + + case 'N': + case 'I': + case 'n': + case 'i': + if (JimParseExprIrrational(pc) == JIM_ERR) + return JimParseExprOperator(pc); + break; + default: + return JimParseExprOperator(pc); + break; + } + return JIM_OK; +} + +static int JimParseExprNumber(struct JimParserCtx *pc) +{ + int allowdot = 1; + int allowhex = 0; + + /* Assume an integer for now */ + pc->tt = JIM_TT_EXPR_INT; + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (isdigit(UCHAR(*pc->p)) + || (allowhex && isxdigit(UCHAR(*pc->p))) + || (allowdot && *pc->p == '.') + || (pc->p - pc->tstart == 1 && *pc->tstart == '0' && (*pc->p == 'x' || *pc->p == 'X')) + ) { + if ((*pc->p == 'x') || (*pc->p == 'X')) { + allowhex = 1; + allowdot = 0; + } + if (*pc->p == '.') { + allowdot = 0; + pc->tt = JIM_TT_EXPR_DOUBLE; + } + pc->p++; + pc->len--; + if (!allowhex && (*pc->p == 'e' || *pc->p == 'E') && (pc->p[1] == '-' || pc->p[1] == '+' + || isdigit(UCHAR(pc->p[1])))) { + pc->p += 2; + pc->len -= 2; + pc->tt = JIM_TT_EXPR_DOUBLE; + } + } + pc->tend = pc->p - 1; + return JIM_OK; +} + +static int JimParseExprIrrational(struct JimParserCtx *pc) +{ + const char *Tokens[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; + const char **token; + + for (token = Tokens; *token != NULL; token++) { + int len = strlen(*token); + + if (strncmp(*token, pc->p, len) == 0) { + pc->tstart = pc->p; + pc->tend = pc->p + len - 1; + pc->p += len; + pc->len -= len; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EXPR_DOUBLE; + return JIM_OK; + } + } + return JIM_ERR; +} + +static int JimParseExprOperator(struct JimParserCtx *pc) +{ + int i; + int bestIdx = -1, bestLen = 0; + + /* Try to get the longest match. */ + for (i = JIM_TT_EXPR_OP; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { + const char *opname; + int oplen; + + opname = Jim_ExprOperators[i].name; + if (opname == NULL) { + continue; + } + oplen = strlen(opname); + + if (strncmp(opname, pc->p, oplen) == 0 && oplen > bestLen) { + bestIdx = i; + bestLen = oplen; + } + } + if (bestIdx == -1) { + return JIM_ERR; + } + + /* Validate paretheses around function arguments */ + if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { + const char *p = pc->p + bestLen; + int len = pc->len - bestLen; + + while (len && isspace(UCHAR(*p))) { + len--; + p++; + } + if (*p != '(') { + return JIM_ERR; + } + } + pc->tstart = pc->p; + pc->tend = pc->p + bestLen - 1; + pc->p += bestLen; + pc->len -= bestLen; + pc->tline = pc->linenr; + + pc->tt = bestIdx; + return JIM_OK; +} + +static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) +{ + return &Jim_ExprOperators[opcode]; +} + +const char *jim_tt_name(int type) +{ + static const char * const tt_names[JIM_TT_EXPR_OP] = + { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", + "DBL", "$()" }; + if (type < JIM_TT_EXPR_OP) { + return tt_names[type]; + } + else { + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); + static char buf[20]; + + if (op && op->name) { + return op->name; + } + sprintf(buf, "(%d)", type); + return buf; + } +} + +/* ----------------------------------------------------------------------------- + * Expression Object + * ---------------------------------------------------------------------------*/ +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType exprObjType = { + "expression", + FreeExprInternalRep, + DupExprInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +/* Expr bytecode structure */ +typedef struct ExprByteCode +{ + int len; /* Length as number of tokens. */ + ScriptToken *token; /* Tokens array. */ + int inUse; /* Used for sharing. */ +} ExprByteCode; + +static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) +{ + int i; + + for (i = 0; i < expr->len; i++) { + Jim_DecrRefCount(interp, expr->token[i].objPtr); + } + Jim_Free(expr->token); + Jim_Free(expr); +} + +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ExprByteCode *expr = (void *)objPtr->internalRep.ptr; + + if (expr) { + if (--expr->inUse != 0) { + return; + } + + ExprFreeByteCode(interp, expr); + } +} + +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + /* Just returns an simple string. */ + dupPtr->typePtr = NULL; +} + +/* Check if an expr program looks correct. */ +static int ExprCheckCorrectness(ExprByteCode * expr) +{ + int i; + int stacklen = 0; + int ternary = 0; + + /* Try to check if there are stack underflows, + * and make sure at the end of the program there is + * a single result on the stack. */ + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op) { + stacklen -= op->arity; + if (stacklen < 0) { + break; + } + if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { + ternary++; + } + else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { + ternary--; + } + } + + /* All operations and operands add one to the stack */ + stacklen++; + } + if (stacklen != 1 || ternary != 0) { + return JIM_ERR; + } + return JIM_OK; +} + +/* This procedure converts every occurrence of || and && opereators + * in lazy unary versions. + * + * a b || is converted into: + * + * a <offset> |L b |R + * + * a b && is converted into: + * + * a <offset> &L b &R + * + * "|L" checks if 'a' is true: + * 1) if it is true pushes 1 and skips <offset> instructions to reach + * the opcode just after |R. + * 2) if it is false does nothing. + * "|R" checks if 'b' is true: + * 1) if it is true pushes 1, otherwise pushes 0. + * + * "&L" checks if 'a' is true: + * 1) if it is true does nothing. + * 2) If it is false pushes 0 and skips <offset> instructions to reach + * the opcode just after &R + * "&R" checks if 'a' is true: + * if it is true pushes 1, otherwise pushes 0. + */ +static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + int i; + + int leftindex, arity, offset; + + /* Search for the end of the first operator */ + leftindex = expr->len - 1; + + arity = 1; + while (arity) { + ScriptToken *tt = &expr->token[leftindex]; + + if (tt->type >= JIM_TT_EXPR_OP) { + arity += JimExprOperatorInfoByOpcode(tt->type)->arity; + } + arity--; + if (--leftindex < 0) { + return JIM_ERR; + } + } + leftindex++; + + /* Move them up */ + memmove(&expr->token[leftindex + 2], &expr->token[leftindex], + sizeof(*expr->token) * (expr->len - leftindex)); + expr->len += 2; + offset = (expr->len - leftindex) - 1; + + /* Now we rely on the fact the the left and right version have opcodes + * 1 and 2 after the main opcode respectively + */ + expr->token[leftindex + 1].type = t->type + 1; + expr->token[leftindex + 1].objPtr = interp->emptyObj; + + expr->token[leftindex].type = JIM_TT_EXPR_INT; + expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); + + /* Now add the 'R' operator */ + expr->token[expr->len].objPtr = interp->emptyObj; + expr->token[expr->len].type = t->type + 2; + expr->len++; + + /* Do we need to adjust the skip count for any &L, |L, ?L or :L in the left operand? */ + for (i = leftindex - 1; i > 0; i--) { + if (JimExprOperatorInfoByOpcode(expr->token[i].type)->lazy == LAZY_LEFT) { + if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { + JimWideValue(expr->token[i - 1].objPtr) += 2; + } + } + } + return JIM_OK; +} + +static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + struct ScriptToken *token = &expr->token[expr->len]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op->lazy == LAZY_OP) { + if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { + Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); + return JIM_ERR; + } + } + else { + token->objPtr = interp->emptyObj; + token->type = t->type; + expr->len++; + } + return JIM_OK; +} + +/** + * Returns the index of the COLON_LEFT to the left of 'right_index' + * taking into account nesting. + * + * The expression *must* be well formed, thus a COLON_LEFT will always be found. + */ +static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) +{ + int ternary_count = 1; + + right_index--; + + while (right_index > 1) { + if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { + ternary_count--; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { + ternary_count++; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { + return right_index; + } + right_index--; + } + + /*notreached*/ + return -1; +} + +/** + * Find the left/right indices for the ternary expression to the left of 'right_index'. + * + * Returns 1 if found, and fills in *prev_right_index and *prev_left_index. + * Otherwise returns 0. + */ +static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) +{ + int i = right_index - 1; + int ternary_count = 1; + + while (i > 1) { + if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { + if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { + *prev_right_index = i - 2; + *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); + return 1; + } + } + else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { + if (ternary_count == 0) { + return 0; + } + ternary_count++; + } + i--; + } + return 0; +} + +/* +* ExprTernaryReorderExpression description +* ======================================== +* +* ?: is right-to-left associative which doesn't work with the stack-based +* expression engine. The fix is to reorder the bytecode. +* +* The expression: +* +* expr 1?2:0?3:4 +* +* Has initial bytecode: +* +* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '0' (44=COLON_RIGHT) +* '2' (40=TERNARY_LEFT) '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) +* +* The fix involves simulating this expression instead: +* +* expr 1?2:(0?3:4) +* +* With the following bytecode: +* +* '1' '2' (40=TERNARY_LEFT) '2' (41=TERNARY_RIGHT) '10' (43=COLON_LEFT) '0' '2' (40=TERNARY_LEFT) +* '3' (41=TERNARY_RIGHT) '2' (43=COLON_LEFT) '4' (44=COLON_RIGHT) (44=COLON_RIGHT) +* +* i.e. The token COLON_RIGHT at index 8 is moved towards the end of the stack, all tokens above 8 +* are shifted down and the skip count of the token JIM_EXPROP_COLON_LEFT at index 5 is +* incremented by the amount tokens shifted down. The token JIM_EXPROP_COLON_RIGHT that is moved +* is identified as immediately preceeding a token JIM_EXPROP_TERNARY_LEFT +* +* ExprTernaryReorderExpression works thus as follows : +* - start from the end of the stack +* - while walking towards the beginning of the stack +* if token=JIM_EXPROP_COLON_RIGHT then +* find the associated token JIM_EXPROP_TERNARY_LEFT, which allows to +* find the associated token previous(JIM_EXPROP_COLON_RIGHT) +* find the associated token previous(JIM_EXPROP_LEFT_RIGHT) +* if all found then +* perform the rotation +* update the skip count of the token previous(JIM_EXPROP_LEFT_RIGHT) +* end if +* end if +* +* Note: care has to be taken for nested ternary constructs!!! +*/ +static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) +{ + int i; + + for (i = expr->len - 1; i > 1; i--) { + int prev_right_index; + int prev_left_index; + int j; + ScriptToken tmp; + + if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { + continue; + } + + /* COLON_RIGHT found: get the indexes needed to move the tokens in the stack (if any) */ + if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { + continue; + } + + /* + ** rotate tokens down + ** + ** +-> [i] : JIM_EXPROP_COLON_RIGHT + ** | | | + ** | V V + ** | [...] : ... + ** | | | + ** | V V + ** | [...] : ... + ** | | | + ** | V V + ** +- [prev_right_index] : JIM_EXPROP_COLON_RIGHT + */ + tmp = expr->token[prev_right_index]; + for (j = prev_right_index; j < i; j++) { + expr->token[j] = expr->token[j + 1]; + } + expr->token[i] = tmp; + + /* Increment the 'skip' count associated to the previous JIM_EXPROP_COLON_LEFT token + * + * This is 'colon left increment' = i - prev_right_index + * + * [prev_left_index] : JIM_EXPROP_LEFT_RIGHT + * [prev_left_index-1] : skip_count + * + */ + JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); + + /* Adjust for i-- in the loop */ + i++; + } +} + +static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) +{ + Jim_Stack stack; + ExprByteCode *expr; + int ok = 1; + int i; + int prevtt = JIM_TT_NONE; + int have_ternary = 0; + + /* -1 for EOL */ + int count = tokenlist->count - 1; + + expr = Jim_Alloc(sizeof(*expr)); + expr->inUse = 1; + expr->len = 0; + + Jim_InitStack(&stack); + + /* Need extra bytecodes for lazy operators. + * Also check for the ternary operator + */ + for (i = 0; i < tokenlist->count; i++) { + ParseToken *t = &tokenlist->list[i]; + + if (JimExprOperatorInfoByOpcode(t->type)->lazy == LAZY_OP) { + count += 2; + /* Ternary is a lazy op but also needs reordering */ + if (t->type == JIM_EXPROP_TERNARY) { + have_ternary = 1; + } + } + } + + expr->token = Jim_Alloc(sizeof(ScriptToken) * count); + + for (i = 0; i < tokenlist->count && ok; i++) { + ParseToken *t = &tokenlist->list[i]; + + /* Next token will be stored here */ + struct ScriptToken *token = &expr->token[expr->len]; + + if (t->type == JIM_TT_EOL) { + break; + } + + switch (t->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + case JIM_TT_VAR: + case JIM_TT_DICTSUGAR: + case JIM_TT_EXPRSUGAR: + case JIM_TT_CMD: + token->objPtr = Jim_NewStringObj(interp, t->token, t->len); + token->type = t->type; + if (t->type == JIM_TT_CMD) { + /* Only commands need source info */ + JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); + } + expr->len++; + break; + + case JIM_TT_EXPR_INT: + token->objPtr = Jim_NewIntObj(interp, strtoull(t->token, NULL, 0)); + token->type = t->type; + expr->len++; + break; + + case JIM_TT_EXPR_DOUBLE: + token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, NULL)); + token->type = t->type; + expr->len++; + break; + + case JIM_TT_SUBEXPR_START: + Jim_StackPush(&stack, t); + prevtt = JIM_TT_NONE; + continue; + + case JIM_TT_SUBEXPR_COMMA: + /* Simple approach. Comma is simply ignored */ + continue; + + case JIM_TT_SUBEXPR_END: + ok = 0; + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 1; + break; + } + + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + goto err; + } + } + if (!ok) { + Jim_SetResultString(interp, "Unexpected close parenthesis", -1); + goto err; + } + break; + + + default:{ + /* Must be an operator */ + const struct Jim_ExprOperator *op; + ParseToken *tt; + + /* Convert -/+ to unary minus or unary plus if necessary */ + if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { + if (t->type == JIM_EXPROP_SUB) { + t->type = JIM_EXPROP_UNARYMINUS; + } + else if (t->type == JIM_EXPROP_ADD) { + t->type = JIM_EXPROP_UNARYPLUS; + } + } + + op = JimExprOperatorInfoByOpcode(t->type); + + /* Now handle precedence */ + while ((tt = Jim_StackPeek(&stack)) != NULL) { + const struct Jim_ExprOperator *tt_op = + JimExprOperatorInfoByOpcode(tt->type); + + /* Note that right-to-left associativity of ?: operator is handled later */ + + if (op->arity != 1 && tt_op->precedence >= op->precedence) { + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + Jim_StackPop(&stack); + } + else { + break; + } + } + Jim_StackPush(&stack, t); + break; + } + } + prevtt = t->type; + } + + /* Reduce any remaining subexpr */ + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 0; + Jim_SetResultString(interp, "Missing close parenthesis", -1); + goto err; + } + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + } + + if (have_ternary) { + ExprTernaryReorderExpression(interp, expr); + } + + err: + /* Free the stack used for the compilation. */ + Jim_FreeStack(&stack); + + for (i = 0; i < expr->len; i++) { + Jim_IncrRefCount(expr->token[i].objPtr); + } + + if (!ok) { + ExprFreeByteCode(interp, expr); + return NULL; + } + + return expr; +} + + +/* This method takes the string representation of an expression + * and generates a program for the Expr's stack-based VM. */ +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int exprTextLen; + const char *exprText; + struct JimParserCtx parser; + struct ExprByteCode *expr; + ParseTokenList tokenlist; + int line; + Jim_Obj *fileNameObj; + int rc = JIM_ERR; + + /* Try to get information about filename / line number */ + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + line = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + Jim_IncrRefCount(fileNameObj); + + exprText = Jim_GetString(objPtr, &exprTextLen); + + /* Initially tokenise the expression into tokenlist */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, exprText, exprTextLen, line); + while (!parser.eof) { + if (JimParseExpression(&parser) != JIM_OK) { + ScriptTokenListFree(&tokenlist); + invalidexpr: + Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); + expr = NULL; + goto err; + } + + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + +#ifdef DEBUG_SHOW_EXPR_TOKENS + { + int i; + printf("==== Expr Tokens ====\n"); + for (i = 0; i < tokenlist.count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), + tokenlist.list[i].len, tokenlist.list[i].token); + } + } +#endif + + /* Now create the expression bytecode from the tokenlist */ + expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + + if (!expr) { + goto err; + } + +#ifdef DEBUG_SHOW_EXPR + { + int i; + + printf("==== Expr ====\n"); + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + + printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } + } +#endif + + /* Check program correctness. */ + if (ExprCheckCorrectness(expr) != JIM_OK) { + ExprFreeByteCode(interp, expr); + goto invalidexpr; + } + + rc = JIM_OK; + + err: + /* Free the old internal rep and set the new one. */ + Jim_DecrRefCount(interp, fileNameObj); + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, expr); + objPtr->typePtr = &exprObjType; + return rc; +} + +static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &exprObjType) { + if (SetExprFromAny(interp, objPtr) != JIM_OK) { + return NULL; + } + } + return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); +} + +/* ----------------------------------------------------------------------------- + * Expressions evaluation. + * Jim uses a specialized stack-based virtual machine for expressions, + * that takes advantage of the fact that expr's operators + * can't be redefined. + * + * Jim_EvalExpression() uses the bytecode compiled by + * SetExprFromAny() method of the "expression" object. + * + * On success a Tcl Object containing the result of the evaluation + * is stored into expResultPtrPtr (having refcount of 1), and JIM_OK is + * returned. + * On error the function returns a retcode != to JIM_OK and set a suitable + * error on the interp. + * ---------------------------------------------------------------------------*/ +#define JIM_EE_STATICSTACK_LEN 10 + +int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) +{ + ExprByteCode *expr; + Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; + int i; + int retcode = JIM_OK; + struct JimExprState e; + + expr = JimGetExpression(interp, exprObjPtr); + if (!expr) { + return JIM_ERR; /* error in expression. */ + } + +#ifdef JIM_OPTIMIZATION + /* Check for one of the following common expressions used by while/for + * + * CONST + * $a + * !$a + * $a < CONST, $a < $b + * $a <= CONST, $a <= $b + * $a > CONST, $a > $b + * $a >= CONST, $a >= $b + * $a != CONST, $a != $b + * $a == CONST, $a == $b + */ + { + Jim_Obj *objPtr; + + /* STEP 1 -- Check if there are the conditions to run the specialized + * version of while */ + + switch (expr->len) { + case 1: + if (expr->token[0].type == JIM_TT_EXPR_INT) { + *exprResultPtrPtr = expr->token[0].objPtr; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + if (expr->token[0].type == JIM_TT_VAR) { + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_ERRMSG); + if (objPtr) { + *exprResultPtrPtr = objPtr; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + + case 2: + if (expr->token[1].type == JIM_EXPROP_NOT && expr->token[0].type == JIM_TT_VAR) { + jim_wide wideValue; + + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValue) == JIM_OK) { + *exprResultPtrPtr = wideValue ? interp->falseObj : interp->trueObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + + case 3: + if (expr->token[0].type == JIM_TT_VAR && (expr->token[1].type == JIM_TT_EXPR_INT + || expr->token[1].type == JIM_TT_VAR)) { + switch (expr->token[2].type) { + case JIM_EXPROP_LT: + case JIM_EXPROP_LTE: + case JIM_EXPROP_GT: + case JIM_EXPROP_GTE: + case JIM_EXPROP_NUMEQ: + case JIM_EXPROP_NUMNE:{ + /* optimise ok */ + jim_wide wideValueA; + jim_wide wideValueB; + + objPtr = Jim_GetVariable(interp, expr->token[0].objPtr, JIM_NONE); + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValueA) == JIM_OK) { + if (expr->token[1].type == JIM_TT_VAR) { + objPtr = + Jim_GetVariable(interp, expr->token[1].objPtr, + JIM_NONE); + } + else { + objPtr = expr->token[1].objPtr; + } + if (objPtr && JimIsWide(objPtr) + && Jim_GetWide(interp, objPtr, &wideValueB) == JIM_OK) { + int cmpRes; + + switch (expr->token[2].type) { + case JIM_EXPROP_LT: + cmpRes = wideValueA < wideValueB; + break; + case JIM_EXPROP_LTE: + cmpRes = wideValueA <= wideValueB; + break; + case JIM_EXPROP_GT: + cmpRes = wideValueA > wideValueB; + break; + case JIM_EXPROP_GTE: + cmpRes = wideValueA >= wideValueB; + break; + case JIM_EXPROP_NUMEQ: + cmpRes = wideValueA == wideValueB; + break; + case JIM_EXPROP_NUMNE: + cmpRes = wideValueA != wideValueB; + break; + default: /*notreached */ + cmpRes = 0; + } + *exprResultPtrPtr = + cmpRes ? interp->trueObj : interp->falseObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + } + } + } + break; + } + } +#endif + + /* In order to avoid that the internal repr gets freed due to + * shimmering of the exprObjPtr's object, we make the internal rep + * shared. */ + expr->inUse++; + + /* The stack-based expr VM itself */ + + /* Stack allocation. Expr programs have the feature that + * a program of length N can't require a stack longer than + * N. */ + if (expr->len > JIM_EE_STATICSTACK_LEN) + e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); + else + e.stack = staticStack; + + e.stacklen = 0; + + /* Execute every instruction */ + for (i = 0; i < expr->len && retcode == JIM_OK; i++) { + Jim_Obj *objPtr; + + switch (expr->token[i].type) { + case JIM_TT_EXPR_INT: + case JIM_TT_EXPR_DOUBLE: + case JIM_TT_STR: + ExprPush(&e, expr->token[i].objPtr); + break; + + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_ESC: + retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); + if (retcode == JIM_OK) { + ExprPush(&e, objPtr); + } + break; + + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, expr->token[i].objPtr); + if (retcode == JIM_OK) { + ExprPush(&e, Jim_GetResult(interp)); + } + break; + + default:{ + /* Find and execute the operation */ + e.skip = 0; + e.opcode = expr->token[i].type; + + retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); + /* Skip some opcodes if necessary */ + i += e.skip; + continue; + } + } + } + + expr->inUse--; + + if (retcode == JIM_OK) { + *exprResultPtrPtr = ExprPop(&e); + } + else { + for (i = 0; i < e.stacklen; i++) { + Jim_DecrRefCount(interp, e.stack[i]); + } + } + if (e.stack != staticStack) { + Jim_Free(e.stack); + } + return retcode; +} + +int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) +{ + int retcode; + jim_wide wideValue; + double doubleValue; + Jim_Obj *exprResultPtr; + + retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); + if (retcode != JIM_OK) + return retcode; + + if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_ERR; + } + else { + Jim_DecrRefCount(interp, exprResultPtr); + *boolPtr = doubleValue != 0; + return JIM_OK; + } + } + *boolPtr = wideValue != 0; + + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * ScanFormat String Object + * ---------------------------------------------------------------------------*/ + +/* This Jim_Obj will held a parsed representation of a format string passed to + * the Jim_ScanString command. For error diagnostics, the scanformat string has + * to be parsed in its entirely first and then, if correct, can be used for + * scanning. To avoid endless re-parsing, the parsed representation will be + * stored in an internal representation and re-used for performance reason. */ + +/* A ScanFmtPartDescr will held the information of /one/ part of the whole + * scanformat string. This part will later be used to extract information + * out from the string to be parsed by Jim_ScanString */ + +typedef struct ScanFmtPartDescr +{ + char type; /* Type of conversion (e.g. c, d, f) */ + char modifier; /* Modify type (e.g. l - long, h - short */ + size_t width; /* Maximal width of input to be converted */ + int pos; /* -1 - no assign, 0 - natural pos, >0 - XPG3 pos */ + char *arg; /* Specification of a CHARSET conversion */ + char *prefix; /* Prefix to be scanned literally before conversion */ +} ScanFmtPartDescr; + +/* The ScanFmtStringObj will hold the internal representation of a scanformat + * string parsed and separated in part descriptions. Furthermore it contains + * the original string representation of the scanformat string to allow for + * fast update of the Jim_Obj's string representation part. + * + * As an add-on the internal object representation adds some scratch pad area + * for usage by Jim_ScanString to avoid endless allocating and freeing of + * memory for purpose of string scanning. + * + * The error member points to a static allocated string in case of a mal- + * formed scanformat string or it contains '0' (NULL) in case of a valid + * parse representation. + * + * The whole memory of the internal representation is allocated as a single + * area of memory that will be internally separated. So freeing and duplicating + * of such an object is cheap */ + +typedef struct ScanFmtStringObj +{ + jim_wide size; /* Size of internal repr in bytes */ + char *stringRep; /* Original string representation */ + size_t count; /* Number of ScanFmtPartDescr contained */ + size_t convCount; /* Number of conversions that will assign */ + size_t maxPos; /* Max position index if XPG3 is used */ + const char *error; /* Ptr to error text (NULL if no error */ + char *scratch; /* Some scratch pad used by Jim_ScanString */ + ScanFmtPartDescr descr[1]; /* The vector of partial descriptions */ +} ScanFmtStringObj; + + +static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfScanFmt(Jim_Obj *objPtr); + +static const Jim_ObjType scanFmtStringObjType = { + "scanformatstring", + FreeScanFmtInternalRep, + DupScanFmtInternalRep, + UpdateStringOfScanFmt, + JIM_TYPE_NONE, +}; + +void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + Jim_Free((char *)objPtr->internalRep.ptr); + objPtr->internalRep.ptr = 0; +} + +void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + size_t size = (size_t) ((ScanFmtStringObj *) srcPtr->internalRep.ptr)->size; + ScanFmtStringObj *newVec = (ScanFmtStringObj *) Jim_Alloc(size); + + JIM_NOTUSED(interp); + memcpy(newVec, srcPtr->internalRep.ptr, size); + dupPtr->internalRep.ptr = newVec; + dupPtr->typePtr = &scanFmtStringObjType; +} + +void UpdateStringOfScanFmt(Jim_Obj *objPtr) +{ + char *bytes = ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep; + + objPtr->bytes = Jim_StrDup(bytes); + objPtr->length = strlen(bytes); +} + +/* SetScanFmtFromAny will parse a given string and create the internal + * representation of the format specification. In case of an error + * the error data member of the internal representation will be set + * to an descriptive error text and the function will be left with + * JIM_ERR to indicate unsucessful parsing (aka. malformed scanformat + * specification */ + +static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ScanFmtStringObj *fmtObj; + char *buffer; + int maxCount, i, approxSize, lastPos = -1; + const char *fmt = objPtr->bytes; + int maxFmtLen = objPtr->length; + const char *fmtEnd = fmt + maxFmtLen; + int curr; + + Jim_FreeIntRep(interp, objPtr); + /* Count how many conversions could take place maximally */ + for (i = 0, maxCount = 0; i < maxFmtLen; ++i) + if (fmt[i] == '%') + ++maxCount; + /* Calculate an approximation of the memory necessary */ + approxSize = sizeof(ScanFmtStringObj) /* Size of the container */ + +(maxCount + 1) * sizeof(ScanFmtPartDescr) /* Size of all partials */ + +maxFmtLen * sizeof(char) + 3 + 1 /* Scratch + "%n" + '\0' */ + + maxFmtLen * sizeof(char) + 1 /* Original stringrep */ + + maxFmtLen * sizeof(char) /* Arg for CHARSETs */ + +(maxCount + 1) * sizeof(char) /* '\0' for every partial */ + +1; /* safety byte */ + fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); + memset(fmtObj, 0, approxSize); + fmtObj->size = approxSize; + fmtObj->maxPos = 0; + fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; + fmtObj->stringRep = fmtObj->scratch + maxFmtLen + 3 + 1; + memcpy(fmtObj->stringRep, fmt, maxFmtLen); + buffer = fmtObj->stringRep + maxFmtLen + 1; + objPtr->internalRep.ptr = fmtObj; + objPtr->typePtr = &scanFmtStringObjType; + for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { + int width = 0, skip; + ScanFmtPartDescr *descr = &fmtObj->descr[curr]; + + fmtObj->count++; + descr->width = 0; /* Assume width unspecified */ + /* Overread and store any "literal" prefix */ + if (*fmt != '%' || fmt[1] == '%') { + descr->type = 0; + descr->prefix = &buffer[i]; + for (; fmt < fmtEnd; ++fmt) { + if (*fmt == '%') { + if (fmt[1] != '%') + break; + ++fmt; + } + buffer[i++] = *fmt; + } + buffer[i++] = 0; + } + /* Skip the conversion introducing '%' sign */ + ++fmt; + /* End reached due to non-conversion literal only? */ + if (fmt >= fmtEnd) + goto done; + descr->pos = 0; /* Assume "natural" positioning */ + if (*fmt == '*') { + descr->pos = -1; /* Okay, conversion will not be assigned */ + ++fmt; + } + else + fmtObj->convCount++; /* Otherwise count as assign-conversion */ + /* Check if next token is a number (could be width or pos */ + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + fmt += skip; + /* Was the number a XPG3 position specifier? */ + if (descr->pos != -1 && *fmt == '$') { + int prev; + + ++fmt; + descr->pos = width; + width = 0; + /* Look if "natural" postioning and XPG3 one was mixed */ + if ((lastPos == 0 && descr->pos > 0) + || (lastPos > 0 && descr->pos == 0)) { + fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; + return JIM_ERR; + } + /* Look if this position was already used */ + for (prev = 0; prev < curr; ++prev) { + if (fmtObj->descr[prev].pos == -1) + continue; + if (fmtObj->descr[prev].pos == descr->pos) { + fmtObj->error = + "variable is assigned by multiple \"%n$\" conversion specifiers"; + return JIM_ERR; + } + } + /* Try to find a width after the XPG3 specifier */ + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + descr->width = width; + fmt += skip; + } + if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) + fmtObj->maxPos = descr->pos; + } + else { + /* Number was not a XPG3, so it has to be a width */ + descr->width = width; + } + } + /* If positioning mode was undetermined yet, fix this */ + if (lastPos == -1) + lastPos = descr->pos; + /* Handle CHARSET conversion type ... */ + if (*fmt == '[') { + int swapped = 1, beg = i, end, j; + + descr->type = '['; + descr->arg = &buffer[i]; + ++fmt; + if (*fmt == '^') + buffer[i++] = *fmt++; + if (*fmt == ']') + buffer[i++] = *fmt++; + while (*fmt && *fmt != ']') + buffer[i++] = *fmt++; + if (*fmt != ']') { + fmtObj->error = "unmatched [ in format string"; + return JIM_ERR; + } + end = i; + buffer[i++] = 0; + /* In case a range fence was given "backwards", swap it */ + while (swapped) { + swapped = 0; + for (j = beg + 1; j < end - 1; ++j) { + if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { + char tmp = buffer[j - 1]; + + buffer[j - 1] = buffer[j + 1]; + buffer[j + 1] = tmp; + swapped = 1; + } + } + } + } + else { + /* Remember any valid modifier if given */ + if (strchr("hlL", *fmt) != 0) + descr->modifier = tolower((int)*fmt++); + + descr->type = *fmt; + if (strchr("efgcsndoxui", *fmt) == 0) { + fmtObj->error = "bad scan conversion character"; + return JIM_ERR; + } + else if (*fmt == 'c' && descr->width != 0) { + fmtObj->error = "field width may not be specified in %c " "conversion"; + return JIM_ERR; + } + else if (*fmt == 'u' && descr->modifier == 'l') { + fmtObj->error = "unsigned wide not supported"; + return JIM_ERR; + } + } + curr++; + } + done: + return JIM_OK; +} + +/* Some accessor macros to allow lowlevel access to fields of internal repr */ + +#define FormatGetCnvCount(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount +#define FormatGetMaxPos(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->maxPos +#define FormatGetError(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error + +/* JimScanAString is used to scan an unspecified string that ends with + * next WS, or a string that is specified via a charset. + * + */ +static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str) +{ + char *buffer = Jim_StrDup(str); + char *p = buffer; + + while (*str) { + int c; + int n; + + if (!sdescr && isspace(UCHAR(*str))) + break; /* EOS via WS if unspecified */ + + n = utf8_tounicode(str, &c); + if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) + break; + while (n--) + *p++ = *str++; + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer); +} + +/* ScanOneEntry will scan one entry out of the string passed as argument. + * It use the sscanf() function for this task. After extracting and + * converting of the value, the count of scanned characters will be + * returned of -1 in case of no conversion tool place and string was + * already scanned thru */ + +static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen, + ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr) +{ + const char *tok; + const ScanFmtPartDescr *descr = &fmtObj->descr[idx]; + size_t scanned = 0; + size_t anchor = pos; + int i; + Jim_Obj *tmpObj = NULL; + + /* First pessimistically assume, we will not scan anything :-) */ + *valObjPtr = 0; + if (descr->prefix) { + /* There was a prefix given before the conversion, skip it and adjust + * the string-to-be-parsed accordingly */ + /* XXX: Should be checking strLen, not str[pos] */ + for (i = 0; pos < strLen && descr->prefix[i]; ++i) { + /* If prefix require, skip WS */ + if (isspace(UCHAR(descr->prefix[i]))) + while (pos < strLen && isspace(UCHAR(str[pos]))) + ++pos; + else if (descr->prefix[i] != str[pos]) + break; /* Prefix do not match here, leave the loop */ + else + ++pos; /* Prefix matched so far, next round */ + } + if (pos >= strLen) { + return -1; /* All of str consumed: EOF condition */ + } + else if (descr->prefix[i] != 0) + return 0; /* Not whole prefix consumed, no conversion possible */ + } + /* For all but following conversion, skip leading WS */ + if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') + while (isspace(UCHAR(str[pos]))) + ++pos; + /* Determine how much skipped/scanned so far */ + scanned = pos - anchor; + + /* %c is a special, simple case. no width */ + if (descr->type == 'n') { + /* Return pseudo conversion means: how much scanned so far? */ + *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); + } + else if (pos >= strLen) { + /* Cannot scan anything, as str is totally consumed */ + return -1; + } + else if (descr->type == 'c') { + int c; + scanned += utf8_tounicode(&str[pos], &c); + *valObjPtr = Jim_NewIntObj(interp, c); + return scanned; + } + else { + /* Processing of conversions follows ... */ + if (descr->width > 0) { + /* Do not try to scan as fas as possible but only the given width. + * To ensure this, we copy the part that should be scanned. */ + size_t sLen = utf8_strlen(&str[pos], strLen - pos); + size_t tLen = descr->width > sLen ? sLen : descr->width; + + tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); + tok = tmpObj->bytes; + } + else { + /* As no width was given, simply refer to the original string */ + tok = &str[pos]; + } + switch (descr->type) { + case 'd': + case 'o': + case 'x': + case 'u': + case 'i':{ + char *endp; /* Position where the number finished */ + jim_wide w; + + int base = descr->type == 'o' ? 8 + : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; + + /* Try to scan a number with the given base */ + w = strtoull(tok, &endp, base); + if (endp == tok && base == 0) { + /* If scanning failed, and base was undetermined, simply + * put it to 10 and try once more. This should catch the + * case where %i begin to parse a number prefix (e.g. + * '0x' but no further digits follows. This will be + * handled as a ZERO followed by a char 'x' by Tcl */ + w = strtoull(tok, &endp, 10); + } + + if (endp != tok) { + /* There was some number sucessfully scanned! */ + *valObjPtr = Jim_NewIntObj(interp, w); + + /* Adjust the number-of-chars scanned so far */ + scanned += endp - tok; + } + else { + /* Nothing was scanned. We have to determine if this + * happened due to e.g. prefix mismatch or input str + * exhausted */ + scanned = *tok ? 0 : -1; + } + break; + } + case 's': + case '[':{ + *valObjPtr = JimScanAString(interp, descr->arg, tok); + scanned += Jim_Length(*valObjPtr); + break; + } + case 'e': + case 'f': + case 'g':{ + char *endp; + double value = strtod(tok, &endp); + + if (endp != tok) { + /* There was some number sucessfully scanned! */ + *valObjPtr = Jim_NewDoubleObj(interp, value); + /* Adjust the number-of-chars scanned so far */ + scanned += endp - tok; + } + else { + /* Nothing was scanned. We have to determine if this + * happened due to e.g. prefix mismatch or input str + * exhausted */ + scanned = *tok ? 0 : -1; + } + break; + } + } + /* If a substring was allocated (due to pre-defined width) do not + * forget to free it */ + if (tmpObj) { + Jim_FreeNewObj(interp, tmpObj); + } + } + return scanned; +} + +/* Jim_ScanString is the workhorse of string scanning. It will scan a given + * string and returns all converted (and not ignored) values in a list back + * to the caller. If an error occured, a NULL pointer will be returned */ + +Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags) +{ + size_t i, pos; + int scanned = 1; + const char *str = Jim_String(strObjPtr); + int strLen = Jim_Utf8Length(interp, strObjPtr); + Jim_Obj *resultList = 0; + Jim_Obj **resultVec = 0; + int resultc; + Jim_Obj *emptyStr = 0; + ScanFmtStringObj *fmtObj; + + /* This should never happen. The format object should already be of the correct type */ + JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); + + fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; + /* Check if format specification was valid */ + if (fmtObj->error != 0) { + if (flags & JIM_ERRMSG) + Jim_SetResultString(interp, fmtObj->error, -1); + return 0; + } + /* Allocate a new "shared" empty string for all unassigned conversions */ + emptyStr = Jim_NewEmptyStringObj(interp); + Jim_IncrRefCount(emptyStr); + /* Create a list and fill it with empty strings up to max specified XPG3 */ + resultList = Jim_NewListObj(interp, 0, 0); + if (fmtObj->maxPos > 0) { + for (i = 0; i < fmtObj->maxPos; ++i) + Jim_ListAppendElement(interp, resultList, emptyStr); + JimListGetElements(interp, resultList, &resultc, &resultVec); + } + /* Now handle every partial format description */ + for (i = 0, pos = 0; i < fmtObj->count; ++i) { + ScanFmtPartDescr *descr = &(fmtObj->descr[i]); + Jim_Obj *value = 0; + + /* Only last type may be "literal" w/o conversion - skip it! */ + if (descr->type == 0) + continue; + /* As long as any conversion could be done, we will proceed */ + if (scanned > 0) + scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); + /* In case our first try results in EOF, we will leave */ + if (scanned == -1 && i == 0) + goto eof; + /* Advance next pos-to-be-scanned for the amount scanned already */ + pos += scanned; + + /* value == 0 means no conversion took place so take empty string */ + if (value == 0) + value = Jim_NewEmptyStringObj(interp); + /* If value is a non-assignable one, skip it */ + if (descr->pos == -1) { + Jim_FreeNewObj(interp, value); + } + else if (descr->pos == 0) + /* Otherwise append it to the result list if no XPG3 was given */ + Jim_ListAppendElement(interp, resultList, value); + else if (resultVec[descr->pos - 1] == emptyStr) { + /* But due to given XPG3, put the value into the corr. slot */ + Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); + Jim_IncrRefCount(value); + resultVec[descr->pos - 1] = value; + } + else { + /* Otherwise, the slot was already used - free obj and ERROR */ + Jim_FreeNewObj(interp, value); + goto err; + } + } + Jim_DecrRefCount(interp, emptyStr); + return resultList; + eof: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return (Jim_Obj *)EOF; + err: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return 0; +} + +/* ----------------------------------------------------------------------------- + * Pseudo Random Number Generation + * ---------------------------------------------------------------------------*/ +/* Initialize the sbox with the numbers from 0 to 255 */ +static void JimPrngInit(Jim_Interp *interp) +{ +#define PRNG_SEED_SIZE 256 + int i; + unsigned int *seed; + time_t t = time(NULL); + + interp->prngState = Jim_Alloc(sizeof(Jim_PrngState)); + + seed = Jim_Alloc(PRNG_SEED_SIZE * sizeof(*seed)); + for (i = 0; i < PRNG_SEED_SIZE; i++) { + seed[i] = (rand() ^ t ^ clock()); + } + JimPrngSeed(interp, (unsigned char *)seed, PRNG_SEED_SIZE * sizeof(*seed)); + Jim_Free(seed); +} + +/* Generates N bytes of random data */ +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len) +{ + Jim_PrngState *prng; + unsigned char *destByte = (unsigned char *)dest; + unsigned int si, sj, x; + + /* initialization, only needed the first time */ + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + /* generates 'len' bytes of pseudo-random numbers */ + for (x = 0; x < len; x++) { + prng->i = (prng->i + 1) & 0xff; + si = prng->sbox[prng->i]; + prng->j = (prng->j + si) & 0xff; + sj = prng->sbox[prng->j]; + prng->sbox[prng->i] = sj; + prng->sbox[prng->j] = si; + *destByte++ = prng->sbox[(si + sj) & 0xff]; + } +} + +/* Re-seed the generator with user-provided bytes */ +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) +{ + int i; + Jim_PrngState *prng; + + /* initialization, only needed the first time */ + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + + /* Set the sbox[i] with i */ + for (i = 0; i < 256; i++) + prng->sbox[i] = i; + /* Now use the seed to perform a random permutation of the sbox */ + for (i = 0; i < seedLen; i++) { + unsigned char t; + + t = prng->sbox[i & 0xFF]; + prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; + prng->sbox[seed[i]] = t; + } + prng->i = prng->j = 0; + + /* discard at least the first 256 bytes of stream. + * borrow the seed buffer for this + */ + for (i = 0; i < 256; i += seedLen) { + JimRandomBytes(interp, seed, seedLen); + } +} + +/* [incr] */ +static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide wideValue, increment = 1; + Jim_Obj *intObjPtr; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) + return JIM_ERR; + } + intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!intObjPtr) { + /* Set missing variable to 0 */ + wideValue = 0; + } + else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { + return JIM_ERR; + } + if (!intObjPtr || Jim_IsShared(intObjPtr)) { + intObjPtr = Jim_NewIntObj(interp, wideValue + increment); + if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, intObjPtr); + return JIM_ERR; + } + } + else { + /* Can do it the quick way */ + Jim_InvalidateStringRep(intObjPtr); + JimWideValue(intObjPtr) = wideValue + increment; + + /* The following step is required in order to invalidate the + * string repr of "FOO" if the var name is on the form of "FOO(IDX)" */ + if (argv[1]->typePtr != &variableObjType) { + /* Note that this can't fail since GetVariable already succeeded */ + Jim_SetVariable(interp, argv[1], intObjPtr); + } + } + Jim_SetResult(interp, intObjPtr); + return JIM_OK; +} + + +/* ----------------------------------------------------------------------------- + * Eval + * ---------------------------------------------------------------------------*/ +#define JIM_EVAL_SARGV_LEN 8 /* static arguments vector length */ +#define JIM_EVAL_SINTV_LEN 8 /* static interpolation vector length */ + +/* Handle calls to the [unknown] command */ +static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *fileNameObj, + int linenr) +{ + Jim_Obj **v, *sv[JIM_EVAL_SARGV_LEN]; + int retCode; + + /* If JimUnknown() is recursively called too many times... + * done here + */ + if (interp->unknown_called > 50) { + return JIM_ERR; + } + + /* If the [unknown] command does not exists returns + * just now */ + if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) + return JIM_ERR; + + /* The object interp->unknown just contains + * the "unknown" string, it is used in order to + * avoid to lookup the unknown command every time + * but instread to cache the result. */ + if (argc + 1 <= JIM_EVAL_SARGV_LEN) + v = sv; + else + v = Jim_Alloc(sizeof(Jim_Obj *) * (argc + 1)); + /* Make a copy of the arguments vector, but shifted on + * the right of one position. The command name of the + * command will be instead the first argument of the + * [unknown] call. */ + memcpy(v + 1, argv, sizeof(Jim_Obj *) * argc); + v[0] = interp->unknown; + /* Call it */ + interp->unknown_called++; + retCode = JimEvalObjVector(interp, argc + 1, v, fileNameObj, linenr); + interp->unknown_called--; + + /* Clean up */ + if (v != sv) + Jim_Free(v); + return retCode; +} + +/* Eval the object vector 'objv' composed of 'objc' elements. + * Every element is used as single argument. + * Jim_EvalObj() will call this function every time its object + * argument is of "list" type, with no string representation. + * + * This is possible because the string representation of a + * list object generated by the UpdateStringOfList is made + * in a way that ensures that every list element is a different + * command argument. */ +static int JimEvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv, + Jim_Obj *fileNameObj, int linenr) +{ + int i, retcode; + Jim_Cmd *cmdPtr; + + /* Incr refcount of arguments. */ + for (i = 0; i < objc; i++) + Jim_IncrRefCount(objv[i]); + /* Command lookup */ + cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); + if (cmdPtr == NULL) { + retcode = JimUnknown(interp, objc, objv, fileNameObj, linenr); + } + else { + /* Call it -- Make sure result is an empty object. */ + JimIncrCmdRefCount(cmdPtr); + Jim_SetEmptyResult(interp); + if (cmdPtr->isproc) { + retcode = JimCallProcedure(interp, cmdPtr, fileNameObj, linenr, objc, objv); + } + else { + interp->cmdPrivData = cmdPtr->u.native.privData; + retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); + } + JimDecrCmdRefCount(interp, cmdPtr); + } + /* Decr refcount of arguments and return the retcode */ + for (i = 0; i < objc; i++) + Jim_DecrRefCount(interp, objv[i]); + + return retcode; +} + +int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + return JimEvalObjVector(interp, objc, objv, interp->emptyObj, 1); +} + +/** + * Invokes 'prefix' as a command with the objv array as arguments. + */ +int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv) +{ + int i; + int ret; + Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv)); + + nargv[0] = prefix; + for (i = 0; i < objc; i++) { + nargv[i + 1] = objv[i]; + } + ret = Jim_EvalObjVector(interp, objc + 1, nargv); + Jim_Free(nargv); + return ret; +} + +static void JimAddErrorToStack(Jim_Interp *interp, int retcode, Jim_Obj *fileNameObj, int line) +{ + int rc = retcode; + + if (rc == JIM_ERR && !interp->errorFlag) { + /* This is the first error, so save the file/line information and reset the stack */ + interp->errorFlag = 1; + Jim_IncrRefCount(fileNameObj); + Jim_DecrRefCount(interp, interp->errorFileNameObj); + interp->errorFileNameObj = fileNameObj; + interp->errorLine = line; + + JimResetStackTrace(interp); + /* Always add a level where the error first occurs */ + interp->addStackTrace++; + } + + /* Now if this is an "interesting" level, add it to the stack trace */ + if (rc == JIM_ERR && interp->addStackTrace > 0) { + /* Add the stack info for the current level */ + + JimAppendStackTrace(interp, Jim_String(interp->errorProc), fileNameObj, line); + + /* Note: if we didn't have a filename for this level, + * don't clear the addStackTrace flag + * so we can pick it up at the next level + */ + if (Jim_Length(fileNameObj)) { + interp->addStackTrace = 0; + } + + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = interp->emptyObj; + Jim_IncrRefCount(interp->errorProc); + } + else if (rc == JIM_RETURN && interp->returnCode == JIM_ERR) { + /* Propagate the addStackTrace value through 'return -code error' */ + } + else { + interp->addStackTrace = 0; + } +} + +/* And delete any local procs */ +static void JimDeleteLocalProcs(Jim_Interp *interp) +{ + if (interp->localProcs) { + char *procname; + + while ((procname = Jim_StackPop(interp->localProcs)) != NULL) { + /* If there is a pushed command, find it */ + Jim_Cmd *prevCmd = NULL; + Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, procname); + if (he) { + Jim_Cmd *cmd = (Jim_Cmd *)he->u.val; + if (cmd->isproc && cmd->u.proc.prevCmd) { + prevCmd = cmd->u.proc.prevCmd; + cmd->u.proc.prevCmd = NULL; + } + } + + /* Delete the local proc */ + Jim_DeleteCommand(interp, procname); + + if (prevCmd) { + /* And restore the pushed command */ + Jim_AddHashEntry(&interp->commands, procname, prevCmd); + } + Jim_Free(procname); + } + Jim_FreeStack(interp->localProcs); + Jim_Free(interp->localProcs); + interp->localProcs = NULL; + } +} + +static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr) +{ + Jim_Obj *objPtr; + + switch (token->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + objPtr = token->objPtr; + break; + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, token->objPtr, JIM_ERRMSG); + break; + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, token->objPtr); + break; + case JIM_TT_EXPRSUGAR: + objPtr = JimExpandExprSugar(interp, token->objPtr); + break; + case JIM_TT_CMD: + switch (Jim_EvalObj(interp, token->objPtr)) { + case JIM_OK: + case JIM_RETURN: + objPtr = interp->result; + break; + case JIM_BREAK: + /* Stop substituting */ + return JIM_BREAK; + case JIM_CONTINUE: + /* just skip this one */ + return JIM_CONTINUE; + default: + return JIM_ERR; + } + break; + default: + JimPanic((1, + "default token type (%d) reached " "in Jim_SubstObj().", token->type)); + objPtr = NULL; + break; + } + if (objPtr) { + *objPtrPtr = objPtr; + return JIM_OK; + } + return JIM_ERR; +} + +/* Interpolate the given tokens into a unique Jim_Obj returned by reference + * via *objPtrPtr. This function is only called by Jim_EvalObj() and Jim_SubstObj() + * The returned object has refcount = 0. + */ +static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags) +{ + int totlen = 0, i; + Jim_Obj **intv; + Jim_Obj *sintv[JIM_EVAL_SINTV_LEN]; + Jim_Obj *objPtr; + char *s; + + if (tokens <= JIM_EVAL_SINTV_LEN) + intv = sintv; + else + intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens); + + /* Compute every token forming the argument + * in the intv objects vector. */ + for (i = 0; i < tokens; i++) { + switch (JimSubstOneToken(interp, &token[i], &intv[i])) { + case JIM_OK: + case JIM_RETURN: + break; + case JIM_BREAK: + if (flags & JIM_SUBST_FLAG) { + /* Stop here */ + tokens = i; + continue; + } + /* XXX: Should probably set an error about break outside loop */ + /* fall through to error */ + case JIM_CONTINUE: + if (flags & JIM_SUBST_FLAG) { + intv[i] = NULL; + continue; + } + /* XXX: Ditto continue outside loop */ + /* fall through to error */ + default: + while (i--) { + Jim_DecrRefCount(interp, intv[i]); + } + if (intv != sintv) { + Jim_Free(intv); + } + return NULL; + } + Jim_IncrRefCount(intv[i]); + Jim_String(intv[i]); + totlen += intv[i]->length; + } + + /* Fast path return for a single token */ + if (tokens == 1 && intv[0] && intv == sintv) { + Jim_DecrRefCount(interp, intv[0]); + return intv[0]; + } + + /* Concatenate every token in an unique + * object. */ + objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); + + if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC + && token[2].type == JIM_TT_VAR) { + /* May be able to do fast interpolated object -> dictSubst */ + objPtr->typePtr = &interpolatedObjType; + objPtr->internalRep.twoPtrValue.ptr1 = (void *)token; + objPtr->internalRep.twoPtrValue.ptr2 = intv[2]; + Jim_IncrRefCount(intv[2]); + } + + s = objPtr->bytes = Jim_Alloc(totlen + 1); + objPtr->length = totlen; + for (i = 0; i < tokens; i++) { + if (intv[i]) { + memcpy(s, intv[i]->bytes, intv[i]->length); + s += intv[i]->length; + Jim_DecrRefCount(interp, intv[i]); + } + } + objPtr->bytes[totlen] = '\0'; + /* Free the intv vector if not static. */ + if (intv != sintv) { + Jim_Free(intv); + } + + return objPtr; +} + + +/* If listPtr is a list, call JimEvalObjVector() with the given source info. + * Otherwise eval with Jim_EvalObj() + */ +static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *fileNameObj, int linenr) +{ + if (!Jim_IsList(listPtr)) { + return Jim_EvalObj(interp, listPtr); + } + else { + int retcode = JIM_OK; + + if (listPtr->internalRep.listValue.len) { + Jim_IncrRefCount(listPtr); + retcode = JimEvalObjVector(interp, + listPtr->internalRep.listValue.len, + listPtr->internalRep.listValue.ele, fileNameObj, linenr); + Jim_DecrRefCount(interp, listPtr); + } + return retcode; + } +} + +int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) +{ + int i; + ScriptObj *script; + ScriptToken *token; + int retcode = JIM_OK; + Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL; + int linenr = 0; + + interp->errorFlag = 0; + + /* If the object is of type "list", with no string rep we can call + * a specialized version of Jim_EvalObj() */ + if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { + return JimEvalObjList(interp, scriptObjPtr, interp->emptyObj, 1); + } + + Jim_IncrRefCount(scriptObjPtr); /* Make sure it's shared. */ + script = Jim_GetScript(interp, scriptObjPtr); + + /* Reset the interpreter result. This is useful to + * return the empty result in the case of empty program. */ + Jim_SetEmptyResult(interp); + +#ifdef JIM_OPTIMIZATION + /* Check for one of the following common scripts used by for, while + * + * {} + * incr a + */ + if (script->len == 0) { + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_OK; + } + if (script->len == 3 + && script->token[1].objPtr->typePtr == &commandObjType + && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0 + && script->token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand + && script->token[2].objPtr->typePtr == &variableObjType) { + + Jim_Obj *objPtr = Jim_GetVariable(interp, script->token[2].objPtr, JIM_NONE); + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + JimWideValue(objPtr)++; + Jim_InvalidateStringRep(objPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } +#endif + + /* Now we have to make sure the internal repr will not be + * freed on shimmering. + * + * Think for example to this: + * + * set x {llength $x; ... some more code ...}; eval $x + * + * In order to preserve the internal rep, we increment the + * inUse field of the script internal rep structure. */ + script->inUse++; + + token = script->token; + argv = sargv; + + /* Execute every command sequentially until the end of the script + * or an error occurs. + */ + for (i = 0; i < script->len && retcode == JIM_OK; ) { + int argc; + int j; + Jim_Cmd *cmd; + + /* First token of the line is always JIM_TT_LINE */ + argc = token[i].objPtr->internalRep.scriptLineValue.argc; + linenr = token[i].objPtr->internalRep.scriptLineValue.line; + + /* Allocate the arguments vector if required */ + if (argc > JIM_EVAL_SARGV_LEN) + argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); + + /* Skip the JIM_TT_LINE token */ + i++; + + /* Populate the arguments objects. + * If an error occurs, retcode will be set and + * 'j' will be set to the number of args expanded + */ + for (j = 0; j < argc; j++) { + long wordtokens = 1; + int expand = 0; + Jim_Obj *wordObjPtr = NULL; + + if (token[i].type == JIM_TT_WORD) { + wordtokens = JimWideValue(token[i++].objPtr); + if (wordtokens < 0) { + expand = 1; + wordtokens = -wordtokens; + } + } + + if (wordtokens == 1) { + /* Fast path if the token does not + * need interpolation */ + + switch (token[i].type) { + case JIM_TT_ESC: + case JIM_TT_STR: + wordObjPtr = token[i].objPtr; + break; + case JIM_TT_VAR: + wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG); + break; + case JIM_TT_EXPRSUGAR: + wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr); + break; + case JIM_TT_DICTSUGAR: + wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr); + break; + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, token[i].objPtr); + if (retcode == JIM_OK) { + wordObjPtr = Jim_GetResult(interp); + } + break; + default: + JimPanic((1, "default token type reached " "in Jim_EvalObj().")); + } + } + else { + /* For interpolation we call a helper + * function to do the work for us. */ + wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE); + } + + if (!wordObjPtr) { + if (retcode == JIM_OK) { + retcode = JIM_ERR; + } + break; + } + + Jim_IncrRefCount(wordObjPtr); + i += wordtokens; + + if (!expand) { + argv[j] = wordObjPtr; + } + else { + /* Need to expand wordObjPtr into multiple args from argv[j] ... */ + int len = Jim_ListLength(interp, wordObjPtr); + int newargc = argc + len - 1; + int k; + + if (len > 1) { + if (argv == sargv) { + if (newargc > JIM_EVAL_SARGV_LEN) { + argv = Jim_Alloc(sizeof(*argv) * newargc); + memcpy(argv, sargv, sizeof(*argv) * j); + } + } + else { + /* Need to realloc to make room for (len - 1) more entries */ + argv = Jim_Realloc(argv, sizeof(*argv) * newargc); + } + } + + /* Now copy in the expanded version */ + for (k = 0; k < len; k++) { + argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; + Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); + } + + /* The original object reference is no longer needed, + * after the expansion it is no longer present on + * the argument vector, but the single elements are + * in its place. */ + Jim_DecrRefCount(interp, wordObjPtr); + + /* And update the indexes */ + j--; + argc += len - 1; + } + } + + if (retcode == JIM_OK && argc) { + /* Lookup the command to call */ + cmd = Jim_GetCommand(interp, argv[0], JIM_ERRMSG); + if (cmd != NULL) { + /* Call it -- Make sure result is an empty object. */ + JimIncrCmdRefCount(cmd); + Jim_SetEmptyResult(interp); + if (cmd->isproc) { + retcode = + JimCallProcedure(interp, cmd, script->fileNameObj, linenr, argc, argv); + } else { + interp->cmdPrivData = cmd->u.native.privData; + retcode = cmd->u.native.cmdProc(interp, argc, argv); + } + JimDecrCmdRefCount(interp, cmd); + } + else { + /* Call [unknown] */ + retcode = JimUnknown(interp, argc, argv, script->fileNameObj, linenr); + } + if (interp->signal_level && interp->sigmask) { + /* Check for a signal after each command */ + retcode = JIM_SIGNAL; + } + } + + /* Finished with the command, so decrement ref counts of each argument */ + while (j-- > 0) { + Jim_DecrRefCount(interp, argv[j]); + } + + if (argv != sargv) { + Jim_Free(argv); + argv = sargv; + } + } + + /* Possibly add to the error stack trace */ + JimAddErrorToStack(interp, retcode, script->fileNameObj, linenr); + + /* Note that we don't have to decrement inUse, because the + * following code transfers our use of the reference again to + * the script object. */ + Jim_FreeIntRep(interp, scriptObjPtr); + scriptObjPtr->typePtr = &scriptObjType; + Jim_SetIntRepPtr(scriptObjPtr, script); + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) +{ + int retcode; + /* If argObjPtr begins with '&', do an automatic upvar */ + const char *varname = Jim_String(argNameObj); + if (*varname == '&') { + /* First check that the target variable exists */ + Jim_Obj *objPtr; + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = interp->framePtr->parentCallFrame; + objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); + interp->framePtr = savedCallFrame; + if (!objPtr) { + return JIM_ERR; + } + + /* It exists, so perform the binding. */ + objPtr = Jim_NewStringObj(interp, varname + 1, -1); + Jim_IncrRefCount(objPtr); + retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parentCallFrame); + Jim_DecrRefCount(interp, objPtr); + } + else { + retcode = Jim_SetVariable(interp, argNameObj, argValObj); + } + return retcode; +} + +/** + * Sets the interp result to be an error message indicating the required proc args. + */ +static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) +{ + /* Create a nice error message, consistent with Tcl 8.5 */ + Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); + int i; + + for (i = 0; i < cmd->u.proc.argListLen; i++) { + Jim_AppendString(interp, argmsg, " ", 1); + + if (i == cmd->u.proc.argsPos) { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + /* Renamed args */ + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); + Jim_AppendString(interp, argmsg, " ...?", -1); + } + else { + /* We have plain args */ + Jim_AppendString(interp, argmsg, "?argument ...?", -1); + } + } + else { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); + Jim_AppendString(interp, argmsg, "?", 1); + } + else { + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); + } + } + } + Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); + Jim_FreeNewObj(interp, argmsg); +} + +/* Call a procedure implemented in Tcl. + * It's possible to speed-up a lot this function, currently + * the callframes are not cached, but allocated and + * destroied every time. What is expecially costly is + * to create/destroy the local vars hash table every time. + * + * This can be fixed just implementing callframes caching + * in JimCreateCallFrame() and JimFreeCallFrame(). */ +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, Jim_Obj *fileNameObj, int linenr, int argc, + Jim_Obj *const *argv) +{ + Jim_CallFrame *callFramePtr; + Jim_Stack *prevLocalProcs; + int i, d, retcode, optargs; + + /* Check arity */ + if (argc - 1 < cmd->u.proc.reqArity || + (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { + JimSetProcWrongArgs(interp, argv[0], cmd); + return JIM_ERR; + } + + /* Check if there are too nested calls */ + if (interp->framePtr->level == interp->maxNestingDepth) { + Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); + return JIM_ERR; + } + + /* Create a new callframe */ + callFramePtr = JimCreateCallFrame(interp, interp->framePtr); + callFramePtr->argv = argv; + callFramePtr->argc = argc; + callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; + callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; + callFramePtr->staticVars = cmd->u.proc.staticVars; + callFramePtr->fileNameObj = fileNameObj; + callFramePtr->line = linenr; + Jim_IncrRefCount(cmd->u.proc.argListObjPtr); + Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); + interp->framePtr = callFramePtr; + + /* How many optional args are available */ + optargs = (argc - 1 - cmd->u.proc.reqArity); + + /* Step 'i' along the actual args, and step 'd' along the formal args */ + i = 1; + for (d = 0; d < cmd->u.proc.argListLen; d++) { + Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; + if (d == cmd->u.proc.argsPos) { + /* assign $args */ + Jim_Obj *listObjPtr; + int argsLen = 0; + if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { + argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); + } + listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); + + /* It is possible to rename args. */ + if (cmd->u.proc.arglist[d].defaultObjPtr) { + nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; + } + retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); + if (retcode != JIM_OK) { + goto badargset; + } + + i += argsLen; + continue; + } + + /* Optional or required? */ + if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { + retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); + } + else { + /* Ran out, so use the default */ + retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); + } + if (retcode != JIM_OK) { + goto badargset; + } + } + + /* Install a new stack for local procs */ + prevLocalProcs = interp->localProcs; + interp->localProcs = NULL; + + /* Eval the body */ + retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); + + /* Delete any local procs */ + JimDeleteLocalProcs(interp); + interp->localProcs = prevLocalProcs; + +badargset: + /* Destroy the callframe */ + interp->framePtr = interp->framePtr->parentCallFrame; + if (callFramePtr->vars.size != JIM_HT_INITIAL_SIZE) { + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NONE); + } + else { + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_NOHT); + } + /* Handle the JIM_EVAL return code */ + while (retcode == JIM_EVAL) { + Jim_Obj *resultScriptObjPtr = Jim_GetResult(interp); + + Jim_IncrRefCount(resultScriptObjPtr); + /* Should be a list! */ + retcode = JimEvalObjList(interp, resultScriptObjPtr, fileNameObj, linenr); + Jim_DecrRefCount(interp, resultScriptObjPtr); + } + /* Handle the JIM_RETURN return code */ + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + else if (retcode == JIM_ERR) { + interp->addStackTrace++; + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = argv[0]; + Jim_IncrRefCount(interp->errorProc); + } + return retcode; +} + +int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) +{ + int retval; + Jim_Obj *scriptObjPtr; + + scriptObjPtr = Jim_NewStringObj(interp, script, -1); + Jim_IncrRefCount(scriptObjPtr); + + if (filename) { + Jim_Obj *prevScriptObj; + + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retval = Jim_EvalObj(interp, scriptObjPtr); + + interp->currentScriptObj = prevScriptObj; + } + else { + retval = Jim_EvalObj(interp, scriptObjPtr); + } + Jim_DecrRefCount(interp, scriptObjPtr); + return retval; +} + +int Jim_Eval(Jim_Interp *interp, const char *script) +{ + return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1)); +} + +/* Execute script in the scope of the global level */ +int Jim_EvalGlobal(Jim_Interp *interp, const char *script) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_Eval(interp, script); + interp->framePtr = savedFramePtr; + + return retval; +} + +int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_EvalFile(interp, filename); + interp->framePtr = savedFramePtr; + + return retval; +} + +#include <sys/stat.h> + +int Jim_EvalFile(Jim_Interp *interp, const char *filename) +{ + FILE *fp; + char *buf; + Jim_Obj *scriptObjPtr; + Jim_Obj *prevScriptObj; + struct stat sb; + int retcode; + int readlen; + struct JimParseResult result; + + if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + if (sb.st_size == 0) { + fclose(fp); + return JIM_OK; + } + + buf = Jim_Alloc(sb.st_size + 1); + readlen = fread(buf, 1, sb.st_size, fp); + if (ferror(fp)) { + fclose(fp); + Jim_Free(buf); + Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + fclose(fp); + buf[readlen] = 0; + + scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); + Jim_IncrRefCount(scriptObjPtr); + + /* Now check the script for unmatched braces, etc. */ + if (SetScriptFromAny(interp, scriptObjPtr, &result) == JIM_ERR) { + const char *msg; + char linebuf[20]; + + switch (result.missing) { + case '[': + msg = "unmatched \"[\""; + break; + case '{': + msg = "missing close-brace"; + break; + case '"': + default: + msg = "missing quote"; + break; + } + + snprintf(linebuf, sizeof(linebuf), "%d", result.line); + + Jim_SetResultFormatted(interp, "%s in \"%s\" at line %s", + msg, filename, linebuf); + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_ERR; + } + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retcode = Jim_EvalObj(interp, scriptObjPtr); + + /* Handle the JIM_RETURN return code */ + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + if (retcode == JIM_ERR) { + /* EvalFile changes context, so add a stack frame here */ + interp->addStackTrace++; + } + + interp->currentScriptObj = prevScriptObj; + + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +/* ----------------------------------------------------------------------------- + * Subst + * ---------------------------------------------------------------------------*/ +static int JimParseSubstStr(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (pc->len && *pc->p != '$' && *pc->p != '[') { + if (*pc->p == '\\' && pc->len > 1) { + pc->p++; + pc->len--; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; +} + +static int JimParseSubst(struct JimParserCtx *pc, int flags) +{ + int retval; + + if (pc->len == 0) { + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*pc->p) { + case '[': + retval = JimParseCmd(pc); + if (flags & JIM_SUBST_NOCMD) { + pc->tstart--; + pc->tend++; + pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC; + } + return retval; + break; + case '$': + if (JimParseVar(pc) == JIM_ERR) { + pc->tstart = pc->tend = pc->p++; + pc->len--; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + } + else { + if (flags & JIM_SUBST_NOVAR) { + pc->tstart--; + if (flags & JIM_SUBST_NOESC) + pc->tt = JIM_TT_STR; + else + pc->tt = JIM_TT_ESC; + if (*pc->tstart == '{') { + pc->tstart--; + if (*(pc->tend + 1)) + pc->tend++; + } + } + } + break; + default: + retval = JimParseSubstStr(pc); + if (flags & JIM_SUBST_NOESC) + pc->tt = JIM_TT_STR; + return retval; + break; + } + return JIM_OK; +} + +/* The subst object type reuses most of the data structures and functions + * of the script object. Script's data structures are a bit more complex + * for what is needed for [subst]itution tasks, but the reuse helps to + * deal with a single data structure at the cost of some more memory + * usage for substitutions. */ + +/* This method takes the string representation of an object + * as a Tcl string where to perform [subst]itution, and generates + * the pre-parsed internal representation. */ +static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script = Jim_Alloc(sizeof(*script)); + ParseTokenList tokenlist; + + /* Initially parse the subst into tokens (in tokenlist) */ + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, 1); + while (1) { + JimParseSubst(&parser, flags); + if (parser.eof) { + /* Note that subst doesn't need the EOL token */ + break; + } + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + + /* Create the "real" subst/script tokens from the initial token list */ + script->inUse = 1; + script->substFlags = flags; + script->fileNameObj = interp->emptyObj; + Jim_IncrRefCount(script->fileNameObj); + SubstObjAddTokens(interp, script, &tokenlist); + + /* No longer need the token list */ + ScriptTokenListFree(&tokenlist); + +#ifdef DEBUG_SHOW_SUBST + { + int i; + + printf("==== Subst ====\n"); + for (i = 0; i < script->len; i++) { + printf("[%2d] %s '%s'\n", i, jim_tt_name(script->token[i].type), + Jim_String(script->token[i].objPtr)); + } + } +#endif + + /* Free the old internal rep and set the new one. */ + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; + return JIM_OK; +} + +static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + if (objPtr->typePtr != &scriptObjType || ((ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags != flags) + SetSubstFromAny(interp, objPtr, flags); + return (ScriptObj *) Jim_GetIntRepPtr(objPtr); +} + +/* Performs commands,variables,blackslashes substitution, + * storing the result object (with refcount 0) into + * resObjPtrPtr. */ +int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) +{ + ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); + + Jim_IncrRefCount(substObjPtr); /* Make sure it's shared. */ + /* In order to preserve the internal rep, we increment the + * inUse field of the script internal rep structure. */ + script->inUse++; + + *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); + + script->inUse--; + Jim_DecrRefCount(interp, substObjPtr); + if (*resObjPtrPtr == NULL) { + return JIM_ERR; + } + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Core commands utility functions + * ---------------------------------------------------------------------------*/ +void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) +{ + int i; + Jim_Obj *objPtr = Jim_NewEmptyStringObj(interp); + + Jim_AppendString(interp, objPtr, "wrong # args: should be \"", -1); + for (i = 0; i < argc; i++) { + Jim_AppendObj(interp, objPtr, argv[i]); + if (!(i + 1 == argc && msg[0] == '\0')) + Jim_AppendString(interp, objPtr, " ", 1); + } + Jim_AppendString(interp, objPtr, msg, -1); + Jim_AppendString(interp, objPtr, "\"", 1); + Jim_SetResult(interp, objPtr); +} + +#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) + +/* type is: 0=commands, 1=procs, 2=channels */ +static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + /* Check for the non-pattern case. We can do this much more efficiently. */ + if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, patternObjPtr, JIM_NONE); + if (cmdPtr) { + if (type == 1 && !cmdPtr->isproc) { + /* not a proc */ + } + else if (type == 2 && !Jim_AioFilehandle(interp, patternObjPtr)) { + /* not a channel */ + } + else { + Jim_ListAppendElement(interp, listObjPtr, patternObjPtr); + } + } + return listObjPtr; + } + + htiter = Jim_GetHashTableIterator(&interp->commands); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_Cmd *cmdPtr = he->u.val; + Jim_Obj *cmdNameObj; + + if (type == 1 && !cmdPtr->isproc) { + /* not a proc */ + continue; + } + if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0)) + continue; + + cmdNameObj = Jim_NewStringObj(interp, he->key, -1); + + /* Is it a channel? */ + if (type == 2 && !Jim_AioFilehandle(interp, cmdNameObj)) { + Jim_FreeNewObj(interp, cmdNameObj); + continue; + } + + Jim_ListAppendElement(interp, listObjPtr, cmdNameObj); + } + Jim_FreeHashTableIterator(htiter); + return listObjPtr; +} + +/* Keep this in order */ +#define JIM_VARLIST_GLOBALS 0 +#define JIM_VARLIST_LOCALS 1 +#define JIM_VARLIST_VARS 2 + +static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + if (mode == JIM_VARLIST_GLOBALS) { + htiter = Jim_GetHashTableIterator(&interp->topFramePtr->vars); + } + else { + /* For [info locals], if we are at top level an emtpy list + * is returned. I don't agree, but we aim at compatibility (SS) */ + if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) + return listObjPtr; + htiter = Jim_GetHashTableIterator(&interp->framePtr->vars); + } + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_Var *varPtr = (Jim_Var *)he->u.val; + + if (mode == JIM_VARLIST_LOCALS) { + if (varPtr->linkFramePtr != NULL) + continue; + } + if (patternObjPtr && !JimStringMatch(interp, patternObjPtr, he->key, 0)) + continue; + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); + } + Jim_FreeHashTableIterator(htiter); + return listObjPtr; +} + +static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, + Jim_Obj **objPtrPtr, int info_level_cmd) +{ + Jim_CallFrame *targetCallFrame; + + targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); + if (targetCallFrame == NULL) { + return JIM_ERR; + } + /* No proc call at toplevel callframe */ + if (targetCallFrame == interp->topFramePtr) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return JIM_ERR; + } + if (info_level_cmd) { + *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); + } + else { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); + Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); + *objPtrPtr = listObj; + } + return JIM_OK; +} + +/* ----------------------------------------------------------------------------- + * Core commands + * ---------------------------------------------------------------------------*/ + +/* fake [puts] -- not the real puts, just for debugging. */ +static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string"); + return JIM_ERR; + } + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) { + Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1); + return JIM_ERR; + } + else { + fputs(Jim_String(argv[2]), stdout); + } + } + else { + puts(Jim_String(argv[1])); + } + return JIM_OK; +} + +/* Helper for [+] and [*] */ +static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res; + double doubleValue, doubleRes; + int i; + + res = (op == JIM_EXPROP_ADD) ? 0 : 1; + + for (i = 1; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) + goto trydouble; + if (op == JIM_EXPROP_ADD) + res += wideValue; + else + res *= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + doubleRes = (double)res; + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_ADD) + doubleRes += doubleValue; + else + doubleRes *= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + +/* Helper for [-] and [/] */ +static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res = 0; + double doubleValue, doubleRes = 0; + int i = 2; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?"); + return JIM_ERR; + } + else if (argc == 2) { + /* The arity = 2 case is different. For [- x] returns -x, + * while [/ x] returns 1/x. */ + if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) { + return JIM_ERR; + } + else { + if (op == JIM_EXPROP_SUB) + doubleRes = -doubleValue; + else + doubleRes = 1.0 / doubleValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; + } + } + if (op == JIM_EXPROP_SUB) { + res = -wideValue; + Jim_SetResultInt(interp, res); + } + else { + doubleRes = 1.0 / wideValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + } + return JIM_OK; + } + else { + if (Jim_GetWide(interp, argv[1], &res) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleRes) + != JIM_OK) { + return JIM_ERR; + } + else { + goto trydouble; + } + } + } + for (i = 2; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { + doubleRes = (double)res; + goto trydouble; + } + if (op == JIM_EXPROP_SUB) + res -= wideValue; + else + res /= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_SUB) + doubleRes -= doubleValue; + else + doubleRes /= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + + +/* [+] */ +static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD); +} + +/* [*] */ +static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL); +} + +/* [-] */ +static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB); +} + +/* [/] */ +static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV); +} + +/* [set] */ +static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *objPtr; + + objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!objPtr) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + /* argc == 3 case. */ + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + +/* [unset] + * + * unset ?-nocomplain? ?--? ?varName ...? + */ +static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i = 1; + int complain = 1; + + while (i < argc) { + if (Jim_CompareStringImmediate(interp, argv[i], "--")) { + i++; + break; + } + if (Jim_CompareStringImmediate(interp, argv[i], "-nocomplain")) { + complain = 0; + i++; + continue; + } + break; + } + + while (i < argc) { + if (Jim_UnsetVariable(interp, argv[i], complain ? JIM_ERRMSG : JIM_NONE) != JIM_OK + && complain) { + return JIM_ERR; + } + i++; + } + return JIM_OK; +} + +/* [while] */ +static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "condition body"); + return JIM_ERR; + } + + /* The general purpose implementation of while starts here */ + while (1) { + int boolean, retval; + + if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) + return retval; + if (!boolean) + break; + + if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) { + switch (retval) { + case JIM_BREAK: + goto out; + break; + case JIM_CONTINUE: + continue; + break; + default: + return retval; + } + } + } + out: + Jim_SetEmptyResult(interp); + return JIM_OK; +} + +/* [for] */ +static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + int boolean = 1; + Jim_Obj *varNamePtr = NULL; + Jim_Obj *stopVarNamePtr = NULL; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "start test next body"); + return JIM_ERR; + } + + /* Do the initialisation */ + if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { + return retval; + } + + /* And do the first test now. Better for optimisation + * if we can do next/test at the bottom of the loop + */ + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + + /* Ready to do the body as follows: + * while (1) { + * body // check retcode + * next // check retcode + * test // check retcode/test bool + * } + */ + +#ifdef JIM_OPTIMIZATION + /* Check if the for is on the form: + * for ... {$i < CONST} {incr i} + * for ... {$i < $j} {incr i} + */ + if (retval == JIM_OK && boolean) { + ScriptObj *incrScript; + ExprByteCode *expr; + jim_wide stop, currentVal; + unsigned jim_wide procEpoch; + Jim_Obj *objPtr; + int cmpOffset; + + /* Do it only if there aren't shared arguments */ + expr = JimGetExpression(interp, argv[2]); + incrScript = Jim_GetScript(interp, argv[3]); + + /* Ensure proper lengths to start */ + if (incrScript->len != 3 || !expr || expr->len != 3) { + goto evalstart; + } + /* Ensure proper token types. */ + if (incrScript->token[1].type != JIM_TT_ESC || + expr->token[0].type != JIM_TT_VAR || + (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { + goto evalstart; + } + + if (expr->token[2].type == JIM_EXPROP_LT) { + cmpOffset = 0; + } + else if (expr->token[2].type == JIM_EXPROP_LTE) { + cmpOffset = 1; + } + else { + goto evalstart; + } + + /* Update command must be incr */ + if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { + goto evalstart; + } + + /* incr, expression must be about the same variable */ + if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { + goto evalstart; + } + + /* Get the stop condition (must be a variable or integer) */ + if (expr->token[1].type == JIM_TT_EXPR_INT) { + if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { + goto evalstart; + } + } + else { + stopVarNamePtr = expr->token[1].objPtr; + Jim_IncrRefCount(stopVarNamePtr); + /* Keep the compiler happy */ + stop = 0; + } + + /* Initialization */ + procEpoch = interp->procEpoch; + varNamePtr = expr->token[0].objPtr; + Jim_IncrRefCount(varNamePtr); + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { + goto testcond; + } + + /* --- OPTIMIZED FOR --- */ + while (retval == JIM_OK) { + /* === Check condition === */ + /* Note that currentVal is already set here */ + + /* Immediate or Variable? get the 'stop' value if the latter. */ + if (stopVarNamePtr) { + objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { + goto testcond; + } + } + + if (currentVal >= stop + cmpOffset) { + break; + } + + /* Eval body */ + retval = Jim_EvalObj(interp, argv[4]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + retval = JIM_OK; + /* If there was a change in procedures/command continue + * with the usual [for] command implementation */ + if (procEpoch != interp->procEpoch) { + goto evalnext; + } + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); + + /* Increment */ + if (objPtr == NULL) { + retval = JIM_ERR; + goto out; + } + if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + currentVal = ++JimWideValue(objPtr); + Jim_InvalidateStringRep(objPtr); + } + else { + if (Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK || + Jim_SetVariable(interp, varNamePtr, Jim_NewIntObj(interp, + ++currentVal)) != JIM_OK) { + goto evalnext; + } + } + } + } + goto out; + } + evalstart: +#endif + + while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { + /* Body */ + retval = Jim_EvalObj(interp, argv[4]); + + if (retval == JIM_OK || retval == JIM_CONTINUE) { + /* increment */ + evalnext: + retval = Jim_EvalObj(interp, argv[3]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + /* test */ + testcond: + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + } + } + } + out: + if (stopVarNamePtr) { + Jim_DecrRefCount(interp, stopVarNamePtr); + } + if (varNamePtr) { + Jim_DecrRefCount(interp, varNamePtr); + } + + if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + + return retval; +} + +/* [loop] */ +static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + jim_wide i; + jim_wide limit; + jim_wide incr = 1; + Jim_Obj *bodyObjPtr; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body"); + return JIM_ERR; + } + + if (Jim_GetWide(interp, argv[2], &i) != JIM_OK || + Jim_GetWide(interp, argv[3], &limit) != JIM_OK || + (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) { + return JIM_ERR; + } + bodyObjPtr = (argc == 5) ? argv[4] : argv[5]; + + retval = Jim_SetVariable(interp, argv[1], argv[2]); + + while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) { + retval = Jim_EvalObj(interp, bodyObjPtr); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + + retval = JIM_OK; + + /* Increment */ + i += incr; + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + return JIM_ERR; + } + } + JimWideValue(objPtr) = i; + Jim_InvalidateStringRep(objPtr); + + /* The following step is required in order to invalidate the + * string repr of "FOO" if the var name is of the form of "FOO(IDX)" */ + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + retval = JIM_ERR; + break; + } + } + } + else { + objPtr = Jim_NewIntObj(interp, i); + retval = Jim_SetVariable(interp, argv[1], objPtr); + if (retval != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + } + } + } + } + + if (retval == JIM_OK || retval == JIM_CONTINUE || retval == JIM_BREAK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + return retval; +} + +/* foreach + lmap implementation. */ +static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) +{ + int result = JIM_ERR, i, nbrOfLists, *listsIdx, *listsEnd; + int nbrOfLoops = 0; + Jim_Obj *emptyStr, *script, *mapRes = NULL; + + if (argc < 4 || argc % 2 != 0) { + Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); + return JIM_ERR; + } + if (doMap) { + mapRes = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(mapRes); + } + emptyStr = Jim_NewEmptyStringObj(interp); + Jim_IncrRefCount(emptyStr); + script = argv[argc - 1]; /* Last argument is a script */ + nbrOfLists = (argc - 1 - 1) / 2; /* argc - 'foreach' - script */ + listsIdx = (int *)Jim_Alloc(nbrOfLists * sizeof(int)); + listsEnd = (int *)Jim_Alloc(nbrOfLists * 2 * sizeof(int)); + /* Initialize iterators and remember max nbr elements each list */ + memset(listsIdx, 0, nbrOfLists * sizeof(int)); + /* Remember lengths of all lists and calculate how much rounds to loop */ + for (i = 0; i < nbrOfLists * 2; i += 2) { + div_t cnt; + int count; + + listsEnd[i] = Jim_ListLength(interp, argv[i + 1]); + listsEnd[i + 1] = Jim_ListLength(interp, argv[i + 2]); + if (listsEnd[i] == 0) { + Jim_SetResultString(interp, "foreach varlist is empty", -1); + goto err; + } + cnt = div(listsEnd[i + 1], listsEnd[i]); + count = cnt.quot + (cnt.rem ? 1 : 0); + if (count > nbrOfLoops) + nbrOfLoops = count; + } + for (; nbrOfLoops-- > 0;) { + for (i = 0; i < nbrOfLists; ++i) { + int varIdx = 0, var = i * 2; + + while (varIdx < listsEnd[var]) { + Jim_Obj *varName, *ele; + int lst = i * 2 + 1; + + /* List index operations below can't fail */ + Jim_ListIndex(interp, argv[var + 1], varIdx, &varName, JIM_NONE); + if (listsIdx[i] < listsEnd[lst]) { + Jim_ListIndex(interp, argv[lst + 1], listsIdx[i], &ele, JIM_NONE); + /* Avoid shimmering */ + Jim_IncrRefCount(ele); + result = Jim_SetVariable(interp, varName, ele); + Jim_DecrRefCount(interp, ele); + if (result == JIM_OK) { + ++listsIdx[i]; /* Remember next iterator of current list */ + ++varIdx; /* Next variable */ + continue; + } + } + else if (Jim_SetVariable(interp, varName, emptyStr) == JIM_OK) { + ++varIdx; /* Next variable */ + continue; + } + goto err; + } + } + switch (result = Jim_EvalObj(interp, script)) { + case JIM_OK: + if (doMap) + Jim_ListAppendElement(interp, mapRes, interp->result); + break; + case JIM_CONTINUE: + break; + case JIM_BREAK: + goto out; + break; + default: + goto err; + } + } + out: + result = JIM_OK; + if (doMap) + Jim_SetResult(interp, mapRes); + else + Jim_SetEmptyResult(interp); + err: + if (doMap) + Jim_DecrRefCount(interp, mapRes); + Jim_DecrRefCount(interp, emptyStr); + Jim_Free(listsIdx); + Jim_Free(listsEnd); + return result; +} + +/* [foreach] */ +static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 0); +} + +/* [lmap] */ +static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 1); +} + +/* [if] */ +static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int boolean, retval, current = 1, falsebody = 0; + + if (argc >= 3) { + while (1) { + /* Far not enough arguments given! */ + if (current >= argc) + goto err; + if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) + != JIM_OK) + return retval; + /* There lacks something, isn't it? */ + if (current >= argc) + goto err; + if (Jim_CompareStringImmediate(interp, argv[current], "then")) + current++; + /* Tsk tsk, no then-clause? */ + if (current >= argc) + goto err; + if (boolean) + return Jim_EvalObj(interp, argv[current]); + /* Ok: no else-clause follows */ + if (++current >= argc) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + return JIM_OK; + } + falsebody = current++; + if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { + /* IIICKS - else-clause isn't last cmd? */ + if (current != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[current]); + } + else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) + /* Ok: elseif follows meaning all the stuff + * again (how boring...) */ + continue; + /* OOPS - else-clause is not last cmd? */ + else if (falsebody != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[falsebody]); + } + return JIM_OK; + } + err: + Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody"); + return JIM_ERR; +} + + +/* Returns 1 if match, 0 if no match or -<error> on error (e.g. -JIM_ERR, -JIM_BREAK)*/ +int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, + Jim_Obj *stringObj, int nocase) +{ + Jim_Obj *parms[4]; + int argc = 0; + long eq; + int rc; + + parms[argc++] = commandObj; + if (nocase) { + parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); + } + parms[argc++] = patternObj; + parms[argc++] = stringObj; + + rc = Jim_EvalObjVector(interp, argc, parms); + + if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { + eq = -rc; + } + + return eq; +} + +enum +{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; + +/* [switch] */ +static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; + Jim_Obj *command = 0, *const *caseList = 0, *strObj; + Jim_Obj *script = 0; + + if (argc < 3) { + wrongnumargs: + Jim_WrongNumArgs(interp, 1, argv, "?options? string " + "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); + return JIM_ERR; + } + for (opt = 1; opt < argc; ++opt) { + const char *option = Jim_String(argv[opt]); + + if (*option != '-') + break; + else if (strncmp(option, "--", 2) == 0) { + ++opt; + break; + } + else if (strncmp(option, "-exact", 2) == 0) + matchOpt = SWITCH_EXACT; + else if (strncmp(option, "-glob", 2) == 0) + matchOpt = SWITCH_GLOB; + else if (strncmp(option, "-regexp", 2) == 0) + matchOpt = SWITCH_RE; + else if (strncmp(option, "-command", 2) == 0) { + matchOpt = SWITCH_CMD; + if ((argc - opt) < 2) + goto wrongnumargs; + command = argv[++opt]; + } + else { + Jim_SetResultFormatted(interp, + "bad option \"%#s\": must be -exact, -glob, -regexp, -command procname or --", + argv[opt]); + return JIM_ERR; + } + if ((argc - opt) < 2) + goto wrongnumargs; + } + strObj = argv[opt++]; + patCount = argc - opt; + if (patCount == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + else + caseList = &argv[opt]; + if (patCount == 0 || patCount % 2 != 0) + goto wrongnumargs; + for (i = 0; script == 0 && i < patCount; i += 2) { + Jim_Obj *patObj = caseList[i]; + + if (!Jim_CompareStringImmediate(interp, patObj, "default") + || i < (patCount - 2)) { + switch (matchOpt) { + case SWITCH_EXACT: + if (Jim_StringEqObj(strObj, patObj)) + script = caseList[i + 1]; + break; + case SWITCH_GLOB: + if (Jim_StringMatchObj(interp, patObj, strObj, 0)) + script = caseList[i + 1]; + break; + case SWITCH_RE: + command = Jim_NewStringObj(interp, "regexp", -1); + /* Fall thru intentionally */ + case SWITCH_CMD:{ + int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); + + /* After the execution of a command we need to + * make sure to reconvert the object into a list + * again. Only for the single-list style [switch]. */ + if (argc - opt == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + /* command is here already decref'd */ + if (rc < 0) { + return -rc; + } + if (rc) + script = caseList[i + 1]; + break; + } + } + } + else { + script = caseList[i + 1]; + } + } + for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) + script = caseList[i + 1]; + if (script && Jim_CompareStringImmediate(interp, script, "-")) { + Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); + return JIM_ERR; + } + Jim_SetEmptyResult(interp); + if (script) { + return Jim_EvalObj(interp, script); + } + return JIM_OK; +} + +/* [list] */ +static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + + listObjPtr = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + +/* [lindex] */ +static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr, *listObjPtr; + int i; + int idx; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "list index ?...?"); + return JIM_ERR; + } + objPtr = argv[1]; + Jim_IncrRefCount(objPtr); + for (i = 2; i < argc; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) { + Jim_DecrRefCount(interp, listObjPtr); + return JIM_ERR; + } + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) { + /* Returns an empty object if the index + * is out of range. */ + Jim_DecrRefCount(interp, listObjPtr); + Jim_SetEmptyResult(interp); + return JIM_OK; + } + Jim_IncrRefCount(objPtr); + Jim_DecrRefCount(interp, listObjPtr); + } + Jim_SetResult(interp, objPtr); + Jim_DecrRefCount(interp, objPtr); + return JIM_OK; +} + +/* [llength] */ +static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1])); + return JIM_OK; +} + +/* [lsearch] */ +static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command", + NULL + }; + enum + { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE, + OPT_COMMAND }; + int i; + int opt_bool = 0; + int opt_not = 0; + int opt_nocase = 0; + int opt_all = 0; + int opt_inline = 0; + int opt_match = OPT_EXACT; + int listlen; + int rc = JIM_OK; + Jim_Obj *listObjPtr = NULL; + Jim_Obj *commandObj = NULL; + + if (argc < 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value"); + return JIM_ERR; + } + + for (i = 1; i < argc - 2; i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_BOOL: + opt_bool = 1; + opt_inline = 0; + break; + case OPT_NOT: + opt_not = 1; + break; + case OPT_NOCASE: + opt_nocase = 1; + break; + case OPT_INLINE: + opt_inline = 1; + opt_bool = 0; + break; + case OPT_ALL: + opt_all = 1; + break; + case OPT_COMMAND: + if (i >= argc - 2) { + goto wrongargs; + } + commandObj = argv[++i]; + /* fallthru */ + case OPT_EXACT: + case OPT_GLOB: + case OPT_REGEXP: + opt_match = option; + break; + } + } + + argv += i; + + if (opt_all) { + listObjPtr = Jim_NewListObj(interp, NULL, 0); + } + if (opt_match == OPT_REGEXP) { + commandObj = Jim_NewStringObj(interp, "regexp", -1); + } + if (commandObj) { + Jim_IncrRefCount(commandObj); + } + + listlen = Jim_ListLength(interp, argv[0]); + for (i = 0; i < listlen; i++) { + Jim_Obj *objPtr; + int eq = 0; + + Jim_ListIndex(interp, argv[0], i, &objPtr, JIM_NONE); + switch (opt_match) { + case OPT_EXACT: + eq = Jim_StringCompareObj(interp, objPtr, argv[1], opt_nocase) == 0; + break; + + case OPT_GLOB: + eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); + break; + + case OPT_REGEXP: + case OPT_COMMAND: + eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); + if (eq < 0) { + if (listObjPtr) { + Jim_FreeNewObj(interp, listObjPtr); + } + rc = JIM_ERR; + goto done; + } + break; + } + + /* If we have a non-match with opt_bool, opt_not, !opt_all, can't exit early */ + if (!eq && opt_bool && opt_not && !opt_all) { + continue; + } + + if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { + /* Got a match (or non-match for opt_not), or (opt_bool && opt_all) */ + Jim_Obj *resultObj; + + if (opt_bool) { + resultObj = Jim_NewIntObj(interp, eq ^ opt_not); + } + else if (!opt_inline) { + resultObj = Jim_NewIntObj(interp, i); + } + else { + resultObj = objPtr; + } + + if (opt_all) { + Jim_ListAppendElement(interp, listObjPtr, resultObj); + } + else { + Jim_SetResult(interp, resultObj); + goto done; + } + } + } + + if (opt_all) { + Jim_SetResult(interp, listObjPtr); + } + else { + /* No match */ + if (opt_bool) { + Jim_SetResultBool(interp, opt_not); + } + else if (!opt_inline) { + Jim_SetResultInt(interp, -1); + } + } + + done: + if (commandObj) { + Jim_DecrRefCount(interp, commandObj); + } + return rc; +} + +/* [lappend] */ +static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + int shared, i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); + return JIM_ERR; + } + listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!listObjPtr) { + /* Create the list if it does not exists */ + listObjPtr = Jim_NewListObj(interp, NULL, 0); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + } + shared = Jim_IsShared(listObjPtr); + if (shared) + listObjPtr = Jim_DuplicateObj(interp, listObjPtr); + for (i = 2; i < argc; i++) + Jim_ListAppendElement(interp, listObjPtr, argv[i]); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + if (shared) + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + +/* [linsert] */ +static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int idx, len; + Jim_Obj *listPtr; + + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "list index element " "?element ...?"); + return JIM_ERR; + } + listPtr = argv[1]; + if (Jim_IsShared(listPtr)) + listPtr = Jim_DuplicateObj(interp, listPtr); + if (Jim_GetIndex(interp, argv[2], &idx) != JIM_OK) + goto err; + len = Jim_ListLength(interp, listPtr); + if (idx >= len) + idx = len; + else if (idx < 0) + idx = len + idx + 1; + Jim_ListInsertElements(interp, listPtr, idx, argc - 3, &argv[3]); + Jim_SetResult(interp, listPtr); + return JIM_OK; + err: + if (listPtr != argv[1]) { + Jim_FreeNewObj(interp, listPtr); + } + return JIM_ERR; +} + +/* [lreplace] */ +static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int first, last, len, rangeLen; + Jim_Obj *listObj; + Jim_Obj *newListObj; + int i; + int shared; + + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last ?element element ...?"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK || + Jim_GetIndex(interp, argv[3], &last) != JIM_OK) { + return JIM_ERR; + } + + listObj = argv[1]; + len = Jim_ListLength(interp, listObj); + + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, first, last, &first, &last, &rangeLen); + + /* Now construct a new list which consists of: + * <elements before first> <supplied elements> <elements after last> + */ + + /* Check to see if trying to replace past the end of the list */ + if (first < len) { + /* OK. Not past the end */ + } + else if (len == 0) { + /* Special for empty list, adjust first to 0 */ + first = 0; + } + else { + Jim_SetResultString(interp, "list doesn't contain element ", -1); + Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); + return JIM_ERR; + } + + newListObj = Jim_NewListObj(interp, NULL, 0); + + shared = Jim_IsShared(listObj); + if (shared) { + listObj = Jim_DuplicateObj(interp, listObj); + } + + /* Add the first set of elements */ + for (i = 0; i < first; i++) { + Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]); + } + + /* Add supplied elements */ + for (i = 4; i < argc; i++) { + Jim_ListAppendElement(interp, newListObj, argv[i]); + } + + /* Add the remaining elements */ + for (i = first + rangeLen; i < len; i++) { + Jim_ListAppendElement(interp, newListObj, listObj->internalRep.listValue.ele[i]); + } + Jim_SetResult(interp, newListObj); + if (shared) { + Jim_FreeNewObj(interp, listObj); + } + return JIM_OK; +} + +/* [lset] */ +static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); + return JIM_ERR; + } + else if (argc == 3) { + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; + } + if (Jim_SetListIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]) + == JIM_ERR) + return JIM_ERR; + return JIM_OK; +} + +/* [lsort] */ +static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) +{ + static const char * const options[] = { + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-index", NULL + }; + enum + { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_INDEX }; + Jim_Obj *resObj; + int i; + int retCode; + + struct lsort_info info; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? list"); + return JIM_ERR; + } + + info.type = JIM_LSORT_ASCII; + info.order = 1; + info.indexed = 0; + info.command = NULL; + info.interp = interp; + + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) + != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_ASCII: + info.type = JIM_LSORT_ASCII; + break; + case OPT_NOCASE: + info.type = JIM_LSORT_NOCASE; + break; + case OPT_INTEGER: + info.type = JIM_LSORT_INTEGER; + break; + case OPT_INCREASING: + info.order = 1; + break; + case OPT_DECREASING: + info.order = -1; + break; + case OPT_COMMAND: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); + return JIM_ERR; + } + info.type = JIM_LSORT_COMMAND; + info.command = argv[i + 1]; + i++; + break; + case OPT_INDEX: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) { + return JIM_ERR; + } + info.indexed = 1; + i++; + break; + } + } + resObj = Jim_DuplicateObj(interp, argv[argc - 1]); + retCode = ListSortElements(interp, resObj, &info); + if (retCode == JIM_OK) { + Jim_SetResult(interp, resObj); + } + else { + Jim_FreeNewObj(interp, resObj); + } + return retCode; +} + +/* [append] */ +static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *stringObjPtr; + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); + return JIM_ERR; + } + if (argc == 2) { + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!stringObjPtr) + return JIM_ERR; + } + else { + int freeobj = 0; + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!stringObjPtr) { + /* Create the string if it doesn't exist */ + stringObjPtr = Jim_NewEmptyStringObj(interp); + freeobj = 1; + } + else if (Jim_IsShared(stringObjPtr)) { + freeobj = 1; + stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); + } + for (i = 2; i < argc; i++) { + Jim_AppendObj(interp, stringObjPtr, argv[i]); + } + if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { + if (freeobj) { + Jim_FreeNewObj(interp, stringObjPtr); + } + return JIM_ERR; + } + } + Jim_SetResult(interp, stringObjPtr); + return JIM_OK; +} + +/* [debug] */ +static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#if defined(JIM_DEBUG_COMMAND) && !defined(JIM_BOOTSTRAP) + static const char * const options[] = { + "refcount", "objcount", "objects", "invstr", "scriptlen", "exprlen", + "exprbc", "show", + NULL + }; + enum + { + OPT_REFCOUNT, OPT_OBJCOUNT, OPT_OBJECTS, OPT_INVSTR, OPT_SCRIPTLEN, + OPT_EXPRLEN, OPT_EXPRBC, OPT_SHOW, + }; + int option; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + if (option == OPT_REFCOUNT) { + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + Jim_SetResultInt(interp, argv[2]->refCount); + return JIM_OK; + } + else if (option == OPT_OBJCOUNT) { + int freeobj = 0, liveobj = 0; + char buf[256]; + Jim_Obj *objPtr; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + /* Count the number of free objects. */ + objPtr = interp->freeList; + while (objPtr) { + freeobj++; + objPtr = objPtr->nextObjPtr; + } + /* Count the number of live objects. */ + objPtr = interp->liveList; + while (objPtr) { + liveobj++; + objPtr = objPtr->nextObjPtr; + } + /* Set the result string and return. */ + sprintf(buf, "free %d used %d", freeobj, liveobj); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; + } + else if (option == OPT_OBJECTS) { + Jim_Obj *objPtr, *listObjPtr, *subListObjPtr; + + /* Count the number of live objects. */ + objPtr = interp->liveList; + listObjPtr = Jim_NewListObj(interp, NULL, 0); + while (objPtr) { + char buf[128]; + const char *type = objPtr->typePtr ? objPtr->typePtr->name : ""; + + subListObjPtr = Jim_NewListObj(interp, NULL, 0); + sprintf(buf, "%p", objPtr); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, buf, -1)); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewStringObj(interp, type, -1)); + Jim_ListAppendElement(interp, subListObjPtr, Jim_NewIntObj(interp, objPtr->refCount)); + Jim_ListAppendElement(interp, subListObjPtr, objPtr); + Jim_ListAppendElement(interp, listObjPtr, subListObjPtr); + objPtr = objPtr->nextObjPtr; + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + else if (option == OPT_INVSTR) { + Jim_Obj *objPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + objPtr = argv[2]; + if (objPtr->typePtr != NULL) + Jim_InvalidateStringRep(objPtr); + Jim_SetEmptyResult(interp); + return JIM_OK; + } + else if (option == OPT_SHOW) { + const char *s; + int len, charlen; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "object"); + return JIM_ERR; + } + s = Jim_GetString(argv[2], &len); +#ifdef JIM_UTF8 + charlen = utf8_strlen(s, len); +#else + charlen = len; +#endif + printf("refcount: %d, type: %s\n", argv[2]->refCount, JimObjTypeName(argv[2])); + printf("chars (%d): <<%s>>\n", charlen, s); + printf("bytes (%d):", len); + while (len--) { + printf(" %02x", (unsigned char)*s++); + } + printf("\n"); + return JIM_OK; + } + else if (option == OPT_SCRIPTLEN) { + ScriptObj *script; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "script"); + return JIM_ERR; + } + script = Jim_GetScript(interp, argv[2]); + Jim_SetResultInt(interp, script->len); + return JIM_OK; + } + else if (option == OPT_EXPRLEN) { + ExprByteCode *expr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "expression"); + return JIM_ERR; + } + expr = JimGetExpression(interp, argv[2]); + if (expr == NULL) + return JIM_ERR; + Jim_SetResultInt(interp, expr->len); + return JIM_OK; + } + else if (option == OPT_EXPRBC) { + Jim_Obj *objPtr; + ExprByteCode *expr; + int i; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "expression"); + return JIM_ERR; + } + expr = JimGetExpression(interp, argv[2]); + if (expr == NULL) + return JIM_ERR; + objPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < expr->len; i++) { + const char *type; + const Jim_ExprOperator *op; + Jim_Obj *obj = expr->token[i].objPtr; + + switch (expr->token[i].type) { + case JIM_TT_EXPR_INT: + type = "int"; + break; + case JIM_TT_EXPR_DOUBLE: + type = "double"; + break; + case JIM_TT_CMD: + type = "command"; + break; + case JIM_TT_VAR: + type = "variable"; + break; + case JIM_TT_DICTSUGAR: + type = "dictsugar"; + break; + case JIM_TT_EXPRSUGAR: + type = "exprsugar"; + break; + case JIM_TT_ESC: + type = "subst"; + break; + case JIM_TT_STR: + type = "string"; + break; + default: + op = JimExprOperatorInfoByOpcode(expr->token[i].type); + if (op == NULL) { + type = "private"; + } + else { + type = "operator"; + } + obj = Jim_NewStringObj(interp, op ? op->name : "", -1); + break; + } + Jim_ListAppendElement(interp, objPtr, Jim_NewStringObj(interp, type, -1)); + Jim_ListAppendElement(interp, objPtr, obj); + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + else { + Jim_SetResultString(interp, + "bad option. Valid options are refcount, " "objcount, objects, invstr", -1); + return JIM_ERR; + } + /* unreached */ +#endif /* JIM_BOOTSTRAP */ +#if !defined(JIM_DEBUG_COMMAND) + Jim_SetResultString(interp, "unsupported", -1); + return JIM_ERR; +#endif +} + +/* [eval] */ +static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int rc; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "script ?...?"); + return JIM_ERR; + } + + if (argc == 2) { + rc = Jim_EvalObj(interp, argv[1]); + } + else { + rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + } + + if (rc == JIM_ERR) { + /* eval is "interesting", so add a stack frame here */ + interp->addStackTrace++; + } + return rc; +} + +/* [uplevel] */ +static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc >= 2) { + int retcode; + Jim_CallFrame *savedCallFrame, *targetCallFrame; + Jim_Obj *objPtr; + const char *str; + + /* Save the old callframe pointer */ + savedCallFrame = interp->framePtr; + + /* Lookup the target frame pointer */ + str = Jim_String(argv[1]); + if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { + targetCallFrame =Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + if (argc < 2) { + argv--; + Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); + return JIM_ERR; + } + /* Eval the code in the target callframe. */ + interp->framePtr = targetCallFrame; + if (argc == 2) { + retcode = Jim_EvalObj(interp, argv[1]); + } + else { + objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(objPtr); + retcode = Jim_EvalObj(interp, objPtr); + Jim_DecrRefCount(interp, objPtr); + } + interp->framePtr = savedCallFrame; + return retcode; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); + return JIM_ERR; + } +} + +/* [expr] */ +static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *exprResultPtr; + int retcode; + + if (argc == 2) { + retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); + } + else if (argc > 2) { + Jim_Obj *objPtr; + + objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(objPtr); + retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); + Jim_DecrRefCount(interp, objPtr); + } + else { + Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); + return JIM_ERR; + } + if (retcode != JIM_OK) + return retcode; + Jim_SetResult(interp, exprResultPtr); + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + +/* [break] */ +static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_BREAK; +} + +/* [continue] */ +static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_CONTINUE; +} + +/* [return] */ +static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_Obj *stackTraceObj = NULL; + Jim_Obj *errorCodeObj = NULL; + int returnCode = JIM_OK; + long level = 1; + + for (i = 1; i < argc - 1; i += 2) { + if (Jim_CompareStringImmediate(interp, argv[i], "-code")) { + if (Jim_GetReturnCode(interp, argv[i + 1], &returnCode) == JIM_ERR) { + return JIM_ERR; + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorinfo")) { + stackTraceObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorcode")) { + errorCodeObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-level")) { + if (Jim_GetLong(interp, argv[i + 1], &level) != JIM_OK || level < 0) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", argv[i + 1]); + return JIM_ERR; + } + } + else { + break; + } + } + + if (i != argc - 1 && i != argc) { + Jim_WrongNumArgs(interp, 1, argv, + "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); + } + + /* If a stack trace is supplied and code is error, set the stack trace */ + if (stackTraceObj && returnCode == JIM_ERR) { + JimSetStackTrace(interp, stackTraceObj); + } + /* If an error code list is supplied, set the global $errorCode */ + if (errorCodeObj && returnCode == JIM_ERR) { + Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); + } + interp->returnCode = returnCode; + interp->returnLevel = level; + + if (i == argc - 1) { + Jim_SetResult(interp, argv[i]); + } + return JIM_RETURN; +} + +/* [tailcall] */ +static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_SetResult(interp, objPtr); + return JIM_EVAL; +} + +/* [proc] */ +static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body"); + return JIM_ERR; + } + + if (argc == 4) { + return JimCreateProcedure(interp, argv[1], argv[2], NULL, argv[3]); + } + else { + return JimCreateProcedure(interp, argv[1], argv[2], argv[3], argv[4]); + } +} + +/* [local] */ +static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retcode; + + /* Evaluate the arguments with 'local' in force */ + interp->local++; + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + interp->local--; + + + /* If OK, and the result is a proc, add it to the list of local procs */ + if (retcode == 0) { + const char *procname = Jim_String(Jim_GetResult(interp)); + + if (Jim_FindHashEntry(&interp->commands, procname) == NULL) { + Jim_SetResultFormatted(interp, "not a proc: \"%s\"", procname); + return JIM_ERR; + } + if (interp->localProcs == NULL) { + interp->localProcs = Jim_Alloc(sizeof(*interp->localProcs)); + Jim_InitStack(interp->localProcs); + } + Jim_StackPush(interp->localProcs, Jim_StrDup(procname)); + } + + return retcode; +} + +/* [upcall] */ +static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); + return JIM_ERR; + } + else { + int retcode; + + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); + if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->u.proc.prevCmd) { + Jim_SetResultFormatted(interp, "no previous proc: \"%#s\"", argv[1]); + return JIM_ERR; + } + /* OK. Mark this command as being in an upcall */ + cmdPtr->u.proc.upcall++; + JimIncrCmdRefCount(cmdPtr); + + /* Invoke the command as normal */ + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + + /* No longer in an upcall */ + cmdPtr->u.proc.upcall--; + JimDecrCmdRefCount(interp, cmdPtr); + + return retcode; + } +} + +/* [concat] */ +static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + return JIM_OK; +} + +/* [upvar] */ +static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_CallFrame *targetCallFrame; + + /* Lookup the target frame pointer */ + if (argc > 3 && (argc % 2 == 0)) { + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + + /* Check for arity */ + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); + return JIM_ERR; + } + + /* Now... for every other/local couple: */ + for (i = 1; i < argc; i += 2) { + if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) + return JIM_ERR; + } + return JIM_OK; +} + +/* [global] */ +static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); + return JIM_ERR; + } + /* Link every var to the toplevel having the same name */ + if (interp->framePtr->level == 0) + return JIM_OK; /* global at toplevel... */ + for (i = 1; i < argc; i++) { + if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) + return JIM_ERR; + } + return JIM_OK; +} + +/* does the [string map] operation. On error NULL is returned, + * otherwise a new string object with the result, having refcount = 0, + * is returned. */ +static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr, + Jim_Obj *objPtr, int nocase) +{ + int numMaps; + const char *str, *noMatchStart = NULL; + int strLen, i; + Jim_Obj *resultObjPtr; + + numMaps = Jim_ListLength(interp, mapListObjPtr); + if (numMaps % 2) { + Jim_SetResultString(interp, "list must contain an even number of elements", -1); + return NULL; + } + + str = Jim_String(objPtr); + strLen = Jim_Utf8Length(interp, objPtr); + + /* Map it */ + resultObjPtr = Jim_NewStringObj(interp, "", 0); + while (strLen) { + for (i = 0; i < numMaps; i += 2) { + Jim_Obj *objPtr; + const char *k; + int kl; + + Jim_ListIndex(interp, mapListObjPtr, i, &objPtr, JIM_NONE); + k = Jim_String(objPtr); + kl = Jim_Utf8Length(interp, objPtr); + + if (strLen >= kl && kl) { + int rc; + if (nocase) { + rc = JimStringCompareNoCase(str, k, kl); + } + else { + rc = JimStringCompare(str, kl, k, kl); + } + if (rc == 0) { + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + noMatchStart = NULL; + } + Jim_ListIndex(interp, mapListObjPtr, i + 1, &objPtr, JIM_NONE); + Jim_AppendObj(interp, resultObjPtr, objPtr); + str += utf8_index(str, kl); + strLen -= kl; + break; + } + } + } + if (i == numMaps) { /* no match */ + int c; + if (noMatchStart == NULL) + noMatchStart = str; + str += utf8_tounicode(str, &c); + strLen--; + } + } + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + } + return resultObjPtr; +} + +/* [string] */ +static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int len; + int opt_case = 1; + int option; + static const char * const options[] = { + "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "map", + "repeat", "reverse", "index", "first", "last", + "trim", "trimleft", "trimright", "tolower", "toupper", NULL + }; + enum + { + OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_MAP, + OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, + OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER + }; + static const char * const nocase_options[] = { + "-nocase", NULL + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) + return JIM_ERR; + + switch (option) { + case OPT_LENGTH: + case OPT_BYTELENGTH: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_LENGTH) { + len = Jim_Utf8Length(interp, argv[2]); + } + else { + len = Jim_Length(argv[2]); + } + Jim_SetResultInt(interp, len); + return JIM_OK; + + case OPT_COMPARE: + case OPT_EQUAL: + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? string1 string2"); + return JIM_ERR; + } + if (opt_case == 0) { + argv++; + } + if (option == OPT_COMPARE || !opt_case) { + Jim_SetResultInt(interp, Jim_StringCompareObj(interp, argv[2], argv[3], !opt_case)); + } + else { + Jim_SetResultBool(interp, Jim_StringEqObj(argv[2], argv[3])); + } + return JIM_OK; + + case OPT_MATCH: + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? pattern string"); + return JIM_ERR; + } + if (opt_case == 0) { + argv++; + } + Jim_SetResultBool(interp, Jim_StringMatchObj(interp, argv[2], argv[3], !opt_case)); + return JIM_OK; + + case OPT_MAP:{ + Jim_Obj *objPtr; + + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList string"); + return JIM_ERR; + } + + if (opt_case == 0) { + argv++; + } + objPtr = JimStringMap(interp, argv[2], argv[3], !opt_case); + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_RANGE: + case OPT_BYTERANGE:{ + Jim_Obj *objPtr; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "string first last"); + return JIM_ERR; + } + if (option == OPT_RANGE) { + objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); + } + else + { + objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); + } + + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REPEAT:{ + Jim_Obj *objPtr; + jim_wide count; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string count"); + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) { + return JIM_ERR; + } + objPtr = Jim_NewStringObj(interp, "", 0); + if (count > 0) { + while (count--) { + Jim_AppendObj(interp, objPtr, argv[2]); + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REVERSE:{ + char *buf, *p; + const char *str; + int len; + int i; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + + str = Jim_GetString(argv[2], &len); + buf = Jim_Alloc(len + 1); + p = buf + len; + *p = 0; + for (i = 0; i < len; ) { + int c; + int l = utf8_tounicode(str, &c); + memcpy(p - l, str, l); + p -= l; + i += l; + str += l; + } + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); + return JIM_OK; + } + + case OPT_INDEX:{ + int idx; + const char *str; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string index"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) { + return JIM_ERR; + } + str = Jim_String(argv[2]); + len = Jim_Utf8Length(interp, argv[2]); + if (idx != INT_MIN && idx != INT_MAX) { + idx = JimRelToAbsIndex(len, idx); + } + if (idx < 0 || idx >= len || str == NULL) { + Jim_SetResultString(interp, "", 0); + } + else if (len == Jim_Length(argv[2])) { + /* ASCII optimisation */ + Jim_SetResultString(interp, str + idx, 1); + } + else { + int c; + int i = utf8_index(str, idx); + Jim_SetResultString(interp, str + i, utf8_tounicode(str + i, &c)); + } + return JIM_OK; + } + + case OPT_FIRST: + case OPT_LAST:{ + int idx = 0, l1, l2; + const char *s1, *s2; + + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?"); + return JIM_ERR; + } + s1 = Jim_String(argv[2]); + s2 = Jim_String(argv[3]); + l1 = Jim_Utf8Length(interp, argv[2]); + l2 = Jim_Utf8Length(interp, argv[3]); + if (argc == 5) { + if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) { + return JIM_ERR; + } + idx = JimRelToAbsIndex(l2, idx); + } + else if (option == OPT_LAST) { + idx = l2; + } + if (option == OPT_FIRST) { + Jim_SetResultInt(interp, JimStringFirst(s1, l1, s2, l2, idx)); + } + else { +#ifdef JIM_UTF8 + Jim_SetResultInt(interp, JimStringLastUtf8(s1, l1, s2, idx)); +#else + Jim_SetResultInt(interp, JimStringLast(s1, l1, s2, idx)); +#endif + } + return JIM_OK; + } + + case OPT_TRIM: + case OPT_TRIMLEFT: + case OPT_TRIMRIGHT:{ + Jim_Obj *trimchars; + + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?"); + return JIM_ERR; + } + trimchars = (argc == 4 ? argv[3] : NULL); + if (option == OPT_TRIM) { + Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMLEFT) { + Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMRIGHT) { + Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars)); + } + return JIM_OK; + } + + case OPT_TOLOWER: + case OPT_TOUPPER: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_TOLOWER) { + Jim_SetResult(interp, JimStringToLower(interp, argv[2])); + } + else { + Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); + } + return JIM_OK; + + case OPT_IS: + if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { + return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); + } + Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); + return JIM_ERR; + } + return JIM_OK; +} + +/* [time] */ +static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long i, count = 1; + jim_wide start, elapsed; + char buf[60]; + const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration"; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "script ?count?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetLong(interp, argv[2], &count) != JIM_OK) + return JIM_ERR; + } + if (count < 0) + return JIM_OK; + i = count; + start = JimClock(); + while (i-- > 0) { + int retval; + + retval = Jim_EvalObj(interp, argv[1]); + if (retval != JIM_OK) { + return retval; + } + } + elapsed = JimClock() - start; + sprintf(buf, fmt, count == 0 ? 0 : elapsed / count); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; +} + +/* [exit] */ +static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long exitCode = 0; + + if (argc > 2) { + Jim_WrongNumArgs(interp, 1, argv, "?exitCode?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK) + return JIM_ERR; + } + interp->exitCode = exitCode; + return JIM_EXIT; +} + +/* [catch] */ +static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int exitCode = 0; + int i; + int sig = 0; + + /* Which return codes are ignored (passed through)? By default, only exit, eval and signal */ + jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); + static const int max_ignore_code = sizeof(ignore_mask) * 8; + + /* Reset the error code before catch. + * Note that this is not strictly correct. + */ + Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); + + for (i = 1; i < argc - 1; i++) { + const char *arg = Jim_String(argv[i]); + jim_wide option; + int ignore; + + /* It's a pity we can't use Jim_GetEnum here :-( */ + if (strcmp(arg, "--") == 0) { + i++; + break; + } + if (*arg != '-') { + break; + } + + if (strncmp(arg, "-no", 3) == 0) { + arg += 3; + ignore = 1; + } + else { + arg++; + ignore = 0; + } + + if (Jim_StringToWide(arg, &option, 10) != JIM_OK) { + option = -1; + } + if (option < 0) { + option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize); + } + if (option < 0) { + goto wrongargs; + } + + if (ignore) { + ignore_mask |= (1 << option); + } + else { + ignore_mask &= ~(1 << option); + } + } + + argc -= i; + if (argc < 1 || argc > 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-?no?code ... --? script ?resultVarName? ?optionVarName?"); + return JIM_ERR; + } + argv += i; + + if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { + sig++; + } + + interp->signal_level += sig; + if (interp->signal_level && interp->sigmask) { + /* If a signal is set, don't even try to execute the body */ + exitCode = JIM_SIGNAL; + } + else { + exitCode = Jim_EvalObj(interp, argv[0]); + } + interp->signal_level -= sig; + + /* Catch or pass through? Only the first 32/64 codes can be passed through */ + if (exitCode >= 0 && exitCode < max_ignore_code && ((1 << exitCode) & ignore_mask)) { + /* Not caught, pass it up */ + return exitCode; + } + + if (sig && exitCode == JIM_SIGNAL) { + /* Catch the signal at this level */ + if (interp->signal_set_result) { + interp->signal_set_result(interp, interp->sigmask); + } + else { + Jim_SetResultInt(interp, interp->sigmask); + } + interp->sigmask = 0; + } + + if (argc >= 2) { + if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) { + return JIM_ERR; + } + if (argc == 3) { + Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); + Jim_ListAppendElement(interp, optListObj, + Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); + Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); + if (exitCode == JIM_ERR) { + Jim_Obj *errorCode; + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", + -1)); + Jim_ListAppendElement(interp, optListObj, interp->stackTrace); + + errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); + if (errorCode) { + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); + Jim_ListAppendElement(interp, optListObj, errorCode); + } + } + if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) { + return JIM_ERR; + } + } + } + Jim_SetResultInt(interp, exitCode); + return JIM_OK; +} + +#ifdef JIM_REFERENCES + +/* [ref] */ +static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); + return JIM_ERR; + } + if (argc == 3) { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); + } + else { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); + } + return JIM_OK; +} + +/* [getref] */ +static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "reference"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, refPtr->objPtr); + return JIM_OK; +} + +/* [setref] */ +static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_IncrRefCount(argv[2]); + Jim_DecrRefCount(interp, refPtr->objPtr); + refPtr->objPtr = argv[2]; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + +/* [collect] */ +static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_Collect(interp)); + + /* Free all the freed objects. */ + while (interp->freeList) { + Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; + Jim_Free(interp->freeList); + interp->freeList = nextObjPtr; + } + + return JIM_OK; +} + +/* [finalize] reference ?newValue? */ +static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *cmdNamePtr; + + if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) + return JIM_ERR; + if (cmdNamePtr != NULL) /* otherwise the null string is returned. */ + Jim_SetResult(interp, cmdNamePtr); + } + else { + if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + } + return JIM_OK; +} + +/* [info references] */ +static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + + listObjPtr = Jim_NewListObj(interp, NULL, 0); + + htiter = Jim_GetHashTableIterator(&interp->references); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + char buf[JIM_REFERENCE_SPACE]; + Jim_Reference *refPtr = he->u.val; + const jim_wide *refId = he->key; + + JimFormatReference(buf, refPtr, *refId); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); + } + Jim_FreeHashTableIterator(htiter); + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} +#endif + +/* [rename] */ +static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *oldName, *newName; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "oldName newName"); + return JIM_ERR; + } + + if (JimValidName(interp, "new procedure", argv[2])) { + return JIM_ERR; + } + + oldName = Jim_String(argv[1]); + newName = Jim_String(argv[2]); + return Jim_RenameCommand(interp, oldName, newName); +} + +int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *dictObj; + Jim_Obj **dictValuesObj; + + if (Jim_DictKeysVector(interp, objPtr, NULL, 0, &dictObj, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + /* XXX: Could make the exact-match case much more efficient here. + * See JimCommandsList() + */ + if (Jim_DictPairs(interp, dictObj, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + /* Only return the matching values */ + resultObj = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, dictValuesObj[i], 0)) { + Jim_ListAppendElement(interp, resultObj, dictValuesObj[i]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetResult(interp, resultObj); + return JIM_OK; +} + +int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return -1; + } + return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; +} + +/* [dict] */ +static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int option; + static const char * const options[] = { + "create", "get", "set", "unset", "exists", "keys", "merge", "size", "with", NULL + }; + enum + { + OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXIST, OPT_KEYS, OPT_MERGE, OPT_SIZE, OPT_WITH, + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); + return JIM_ERR; + } + + if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + switch (option) { + case OPT_GET: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); + return JIM_ERR; + } + if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, + JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + + case OPT_SET: + if (argc < 5) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); + return JIM_ERR; + } + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); + + case OPT_EXIST: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName ?key ...?"); + return JIM_ERR; + } + Jim_SetResultBool(interp, Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, + &objPtr, JIM_ERRMSG) == JIM_OK); + return JIM_OK; + + case OPT_UNSET: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); + return JIM_ERR; + } + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE); + + case OPT_KEYS: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar ?pattern?"); + return JIM_ERR; + } + return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); + + case OPT_SIZE: { + int size; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar"); + return JIM_ERR; + } + + size = Jim_DictSize(interp, argv[2]); + if (size < 0) { + return JIM_ERR; + } + Jim_SetResultInt(interp, size); + return JIM_OK; + } + + case OPT_MERGE: + if (argc == 2) { + return JIM_OK; + } + else if (argv[2]->typePtr != &dictObjType && SetDictFromAny(interp, argv[2]) != JIM_OK) { + return JIM_ERR; + } + else { + return Jim_EvalPrefix(interp, "dict merge", argc - 2, argv + 2); + } + + case OPT_WITH: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictVar ?key ...? script"); + return JIM_ERR; + } + else if (Jim_GetVariable(interp, argv[2], JIM_ERRMSG) == NULL) { + return JIM_ERR; + } + else { + return Jim_EvalPrefix(interp, "dict with", argc - 2, argv + 2); + } + + case OPT_CREATE: + if (argc % 2) { + Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); + return JIM_ERR; + } + objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); + Jim_SetResult(interp, objPtr); + return JIM_OK; + + default: + abort(); + } +} + +/* [subst] */ +static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-nobackslashes", "-nocommands", "-novariables", NULL + }; + enum + { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES }; + int i; + int flags = JIM_SUBST_FLAG; + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? string"); + return JIM_ERR; + } + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NOBACKSLASHES: + flags |= JIM_SUBST_NOESC; + break; + case OPT_NOCOMMANDS: + flags |= JIM_SUBST_NOCMD; + break; + case OPT_NOVARIABLES: + flags |= JIM_SUBST_NOVAR; + break; + } + } + if (Jim_SubstObj(interp, argv[argc - 1], &objPtr, flags) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [info] */ +static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int cmd; + Jim_Obj *objPtr; + int mode = 0; + + static const char * const commands[] = { + "body", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals", + "vars", "version", "patchlevel", "complete", "args", "hostname", + "script", "source", "stacktrace", "nameofexecutable", "returncodes", + "references", NULL + }; + enum + { INFO_BODY, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, + INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, + INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, + INFO_RETURNCODES, INFO_REFERENCES, + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) + != JIM_OK) { + return JIM_ERR; + } + + /* Test for the the most common commands first, just in case it makes a difference */ + switch (cmd) { + case INFO_EXISTS:{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName"); + return JIM_ERR; + } + Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL); + break; + } + + case INFO_CHANNELS: +#ifndef jim_ext_aio + Jim_SetResultString(interp, "aio not enabled", -1); + return JIM_ERR; +#endif + case INFO_COMMANDS: + case INFO_PROCS: + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } + Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, + (cmd - INFO_COMMANDS))); + break; + + case INFO_VARS: + mode++; /* JIM_VARLIST_VARS */ + case INFO_LOCALS: + mode++; /* JIM_VARLIST_LOCALS */ + case INFO_GLOBALS: + /* mode 0 => JIM_VARLIST_GLOBALS */ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } + Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode)); + break; + + case INFO_SCRIPT: + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_GetScript(interp, interp->currentScriptObj)->fileNameObj); + break; + + case INFO_SOURCE:{ + int line; + Jim_Obj *resObjPtr; + Jim_Obj *fileNameObj; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "source"); + return JIM_ERR; + } + if (argv[2]->typePtr == &sourceObjType) { + fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj; + line = argv[2]->internalRep.sourceValue.lineNumber; + } + else if (argv[2]->typePtr == &scriptObjType) { + ScriptObj *script = Jim_GetScript(interp, argv[2]); + fileNameObj = script->fileNameObj; + line = script->line; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + resObjPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, resObjPtr, fileNameObj); + Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); + Jim_SetResult(interp, resObjPtr); + break; + } + + case INFO_STACKTRACE: + Jim_SetResult(interp, interp->stackTrace); + break; + + case INFO_LEVEL: + case INFO_FRAME: + switch (argc) { + case 2: + Jim_SetResultInt(interp, interp->framePtr->level); + break; + + case 3: + if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + break; + + default: + Jim_WrongNumArgs(interp, 2, argv, "?levelNum?"); + return JIM_ERR; + } + break; + + case INFO_BODY: + case INFO_ARGS:{ + Jim_Cmd *cmdPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "procname"); + return JIM_ERR; + } + if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { + return JIM_ERR; + } + if (!cmdPtr->isproc) { + Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]); + return JIM_ERR; + } + Jim_SetResult(interp, + cmd == INFO_BODY ? cmdPtr->u.proc.bodyObjPtr : cmdPtr->u.proc.argListObjPtr); + break; + } + + case INFO_VERSION: + case INFO_PATCHLEVEL:{ + char buf[(JIM_INTEGER_SPACE * 2) + 1]; + + sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetResultString(interp, buf, -1); + break; + } + + case INFO_COMPLETE: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "script ?missing?"); + return JIM_ERR; + } + else { + int len; + const char *s = Jim_GetString(argv[2], &len); + char missing; + + Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing)); + if (missing != ' ' && argc == 4) { + Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1)); + } + } + break; + + case INFO_HOSTNAME: + /* Redirect to os.gethostname if it exists */ + return Jim_Eval(interp, "os.gethostname"); + + case INFO_NAMEOFEXECUTABLE: + /* Redirect to Tcl proc */ + return Jim_Eval(interp, "{info nameofexecutable}"); + + case INFO_RETURNCODES: + if (argc == 2) { + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; jimReturnCodes[i]; i++) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewIntObj(interp, i)); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, + jimReturnCodes[i], -1)); + } + + Jim_SetResult(interp, listObjPtr); + } + else if (argc == 3) { + long code; + const char *name; + + if (Jim_GetLong(interp, argv[2], &code) != JIM_OK) { + return JIM_ERR; + } + name = Jim_ReturnCode(code); + if (*name == '?') { + Jim_SetResultInt(interp, code); + } + else { + Jim_SetResultString(interp, name, -1); + } + } + else { + Jim_WrongNumArgs(interp, 2, argv, "?code?"); + return JIM_ERR; + } + break; + case INFO_REFERENCES: +#ifdef JIM_REFERENCES + return JimInfoReferences(interp, argc, argv); +#else + Jim_SetResultString(interp, "not supported", -1); + return JIM_ERR; +#endif + } + return JIM_OK; +} + +/* [exists] */ +static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + static const char * const options[] = { + "-command", "-proc", "-var", NULL + }; + enum + { + OPT_COMMAND, OPT_PROC, OPT_VAR + }; + int option; + + if (argc == 2) { + option = OPT_VAR; + objPtr = argv[1]; + } + else if (argc == 3) { + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + objPtr = argv[2]; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?option? name"); + return JIM_ERR; + } + + /* Test for the the most common commands first, just in case it makes a difference */ + switch (option) { + case OPT_VAR: + Jim_SetResultBool(interp, Jim_GetVariable(interp, objPtr, 0) != NULL); + break; + + case OPT_COMMAND: + case OPT_PROC: { + Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); + Jim_SetResultBool(interp, cmd != NULL && (option == OPT_COMMAND || cmd->isproc)); + break; + } + } + return JIM_OK; +} + +/* [split] */ +static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *str, *splitChars, *noMatchStart; + int splitLen, strLen; + Jim_Obj *resObjPtr; + int c; + int len; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?"); + return JIM_ERR; + } + + str = Jim_GetString(argv[1], &len); + if (len == 0) { + return JIM_OK; + } + strLen = Jim_Utf8Length(interp, argv[1]); + + /* Init */ + if (argc == 2) { + splitChars = " \n\t\r"; + splitLen = 4; + } + else { + splitChars = Jim_String(argv[2]); + splitLen = Jim_Utf8Length(interp, argv[2]); + } + + noMatchStart = str; + resObjPtr = Jim_NewListObj(interp, NULL, 0); + + /* Split */ + if (splitLen) { + Jim_Obj *objPtr; + while (strLen--) { + const char *sc = splitChars; + int scLen = splitLen; + int sl = utf8_tounicode(str, &c); + while (scLen--) { + int pc; + sc += utf8_tounicode(sc, &pc); + if (c == pc) { + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + noMatchStart = str + sl; + break; + } + } + str += sl; + } + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + } + else { + /* This handles the special case of splitchars eq {} + * Optimise by sharing common (ASCII) characters + */ + Jim_Obj **commonObj = NULL; +#define NUM_COMMON (128 - 9) + while (strLen--) { + int n = utf8_tounicode(str, &c); +#ifdef JIM_OPTIMIZATION + if (c >= 9 && c < 128) { + /* Common ASCII char. Note that 9 is the tab character */ + c -= 9; + if (!commonObj) { + commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); + memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); + } + if (!commonObj[c]) { + commonObj[c] = Jim_NewStringObj(interp, str, 1); + } + Jim_ListAppendElement(interp, resObjPtr, commonObj[c]); + str++; + continue; + } +#endif + Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObjUtf8(interp, str, 1)); + str += n; + } + Jim_Free(commonObj); + } + + Jim_SetResult(interp, resObjPtr); + return JIM_OK; +} + +/* [join] */ +static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *joinStr; + int joinStrLen, i, listLen; + Jim_Obj *resObjPtr; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); + return JIM_ERR; + } + /* Init */ + if (argc == 2) { + joinStr = " "; + joinStrLen = 1; + } + else { + joinStr = Jim_GetString(argv[2], &joinStrLen); + } + listLen = Jim_ListLength(interp, argv[1]); + resObjPtr = Jim_NewStringObj(interp, NULL, 0); + /* Split */ + for (i = 0; i < listLen; i++) { + Jim_Obj *objPtr = 0; + + Jim_ListIndex(interp, argv[1], i, &objPtr, JIM_NONE); + Jim_AppendObj(interp, resObjPtr, objPtr); + if (i + 1 != listLen) { + Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); + } + } + Jim_SetResult(interp, resObjPtr); + return JIM_OK; +} + +/* [format] */ +static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?"); + return JIM_ERR; + } + objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2); + if (objPtr == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [scan] */ +static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listPtr, **outVec; + int outc, i; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?"); + return JIM_ERR; + } + if (argv[2]->typePtr != &scanFmtStringObjType) + SetScanFmtFromAny(interp, argv[2]); + if (FormatGetError(argv[2]) != 0) { + Jim_SetResultString(interp, FormatGetError(argv[2]), -1); + return JIM_ERR; + } + if (argc > 3) { + int maxPos = FormatGetMaxPos(argv[2]); + int count = FormatGetCnvCount(argv[2]); + + if (maxPos > argc - 3) { + Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1); + return JIM_ERR; + } + else if (count > argc - 3) { + Jim_SetResultString(interp, "different numbers of variable names and " + "field specifiers", -1); + return JIM_ERR; + } + else if (count < argc - 3) { + Jim_SetResultString(interp, "variable is not assigned by any " + "conversion specifiers", -1); + return JIM_ERR; + } + } + listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG); + if (listPtr == 0) + return JIM_ERR; + if (argc > 3) { + int rc = JIM_OK; + int count = 0; + + if (listPtr != 0 && listPtr != (Jim_Obj *)EOF) { + int len = Jim_ListLength(interp, listPtr); + + if (len != 0) { + JimListGetElements(interp, listPtr, &outc, &outVec); + for (i = 0; i < outc; ++i) { + if (Jim_Length(outVec[i]) > 0) { + ++count; + if (Jim_SetVariable(interp, argv[3 + i], outVec[i]) != JIM_OK) { + rc = JIM_ERR; + } + } + } + } + Jim_FreeNewObj(interp, listPtr); + } + else { + count = -1; + } + if (rc == JIM_OK) { + Jim_SetResultInt(interp, count); + } + return rc; + } + else { + if (listPtr == (Jim_Obj *)EOF) { + Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0)); + return JIM_OK; + } + Jim_SetResult(interp, listPtr); + } + return JIM_OK; +} + +/* [error] */ +static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?"); + return JIM_ERR; + } + Jim_SetResult(interp, argv[1]); + if (argc == 3) { + JimSetStackTrace(interp, argv[2]); + return JIM_ERR; + } + interp->addStackTrace++; + return JIM_ERR; +} + +/* [lrange] */ +static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last"); + return JIM_ERR; + } + if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [lrepeat] */ +static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + long count; + + if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) { + Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?"); + return JIM_ERR; + } + + if (count == 0 || argc == 2) { + return JIM_OK; + } + + argc -= 2; + argv += 2; + + objPtr = Jim_NewListObj(interp, argv, argc); + while (--count) { + int i; + + for (i = 0; i < argc; i++) { + ListAppendElement(objPtr, argv[i]); + } + } + + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +char **Jim_GetEnviron(void) +{ +#if defined(HAVE__NSGETENVIRON) + return *_NSGetEnviron(); +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + return environ; +#endif +} + +void Jim_SetEnviron(char **env) +{ +#if defined(HAVE__NSGETENVIRON) + *_NSGetEnviron() = env; +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + environ = env; +#endif +} + +/* [env] */ +static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *key; + const char *val; + + if (argc == 1) { + char **e = Jim_GetEnviron(); + + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; e[i]; i++) { + const char *equals = strchr(e[i], '='); + + if (equals) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, e[i], + equals - e[i])); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1)); + } + } + + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?default?"); + return JIM_ERR; + } + key = Jim_String(argv[1]); + val = getenv(key); + if (val == NULL) { + if (argc < 3) { + Jim_SetResultFormatted(interp, "environment variable \"%#s\" does not exist", argv[1]); + return JIM_ERR; + } + val = Jim_String(argv[2]); + } + Jim_SetResult(interp, Jim_NewStringObj(interp, val, -1)); + return JIM_OK; +} + +/* [source] */ +static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "fileName"); + return JIM_ERR; + } + retval = Jim_EvalFile(interp, Jim_String(argv[1])); + if (retval == JIM_RETURN) + return JIM_OK; + return retval; +} + +/* [lreverse] */ +static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *revObjPtr, **ele; + int len; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + JimListGetElements(interp, argv[1], &len, &ele); + len--; + revObjPtr = Jim_NewListObj(interp, NULL, 0); + while (len >= 0) + ListAppendElement(revObjPtr, ele[len--]); + Jim_SetResult(interp, revObjPtr); + return JIM_OK; +} + +static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step) +{ + jim_wide len; + + if (step == 0) + return -1; + if (start == end) + return 0; + else if (step > 0 && start > end) + return -1; + else if (step < 0 && end > start) + return -1; + len = end - start; + if (len < 0) + len = -len; /* abs(len) */ + if (step < 0) + step = -step; /* abs(step) */ + len = 1 + ((len - 1) / step); + /* We can truncate safely to INT_MAX, the range command + * will always return an error for a such long range + * because Tcl lists can't be so long. */ + if (len > INT_MAX) + len = INT_MAX; + return (int)((len < 0) ? -1 : len); +} + +/* [range] */ +static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide start = 0, end, step = 1; + int len, i; + Jim_Obj *objPtr; + + if (argc < 2 || argc > 4) { + Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &end) != JIM_OK) + return JIM_ERR; + } + else { + if (Jim_GetWide(interp, argv[1], &start) != JIM_OK || + Jim_GetWide(interp, argv[2], &end) != JIM_OK) + return JIM_ERR; + if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK) + return JIM_ERR; + } + if ((len = JimRangeLen(start, end, step)) == -1) { + Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1); + return JIM_ERR; + } + objPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < len; i++) + ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step)); + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +/* [rand] */ +static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide min = 0, max = 0, len, maxMul; + + if (argc < 1 || argc > 3) { + Jim_WrongNumArgs(interp, 1, argv, "?min? max"); + return JIM_ERR; + } + if (argc == 1) { + max = JIM_WIDE_MAX; + } else if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &max) != JIM_OK) + return JIM_ERR; + } else if (argc == 3) { + if (Jim_GetWide(interp, argv[1], &min) != JIM_OK || + Jim_GetWide(interp, argv[2], &max) != JIM_OK) + return JIM_ERR; + } + len = max-min; + if (len < 0) { + Jim_SetResultString(interp, "Invalid arguments (max < min)", -1); + return JIM_ERR; + } + maxMul = JIM_WIDE_MAX - (len ? (JIM_WIDE_MAX%len) : 0); + while (1) { + jim_wide r; + + JimRandomBytes(interp, &r, sizeof(jim_wide)); + if (r < 0 || r >= maxMul) continue; + r = (len == 0) ? 0 : r%len; + Jim_SetResultInt(interp, min+r); + return JIM_OK; + } +} + +static const struct { + const char *name; + Jim_CmdProc cmdProc; +} Jim_CoreCommandsTable[] = { + {"set", Jim_SetCoreCommand}, + {"unset", Jim_UnsetCoreCommand}, + {"puts", Jim_PutsCoreCommand}, + {"+", Jim_AddCoreCommand}, + {"*", Jim_MulCoreCommand}, + {"-", Jim_SubCoreCommand}, + {"/", Jim_DivCoreCommand}, + {"incr", Jim_IncrCoreCommand}, + {"while", Jim_WhileCoreCommand}, + {"loop", Jim_LoopCoreCommand}, + {"for", Jim_ForCoreCommand}, + {"foreach", Jim_ForeachCoreCommand}, + {"lmap", Jim_LmapCoreCommand}, + {"if", Jim_IfCoreCommand}, + {"switch", Jim_SwitchCoreCommand}, + {"list", Jim_ListCoreCommand}, + {"lindex", Jim_LindexCoreCommand}, + {"lset", Jim_LsetCoreCommand}, + {"lsearch", Jim_LsearchCoreCommand}, + {"llength", Jim_LlengthCoreCommand}, + {"lappend", Jim_LappendCoreCommand}, + {"linsert", Jim_LinsertCoreCommand}, + {"lreplace", Jim_LreplaceCoreCommand}, + {"lsort", Jim_LsortCoreCommand}, + {"append", Jim_AppendCoreCommand}, + {"debug", Jim_DebugCoreCommand}, + {"eval", Jim_EvalCoreCommand}, + {"uplevel", Jim_UplevelCoreCommand}, + {"expr", Jim_ExprCoreCommand}, + {"break", Jim_BreakCoreCommand}, + {"continue", Jim_ContinueCoreCommand}, + {"proc", Jim_ProcCoreCommand}, + {"concat", Jim_ConcatCoreCommand}, + {"return", Jim_ReturnCoreCommand}, + {"upvar", Jim_UpvarCoreCommand}, + {"global", Jim_GlobalCoreCommand}, + {"string", Jim_StringCoreCommand}, + {"time", Jim_TimeCoreCommand}, + {"exit", Jim_ExitCoreCommand}, + {"catch", Jim_CatchCoreCommand}, +#ifdef JIM_REFERENCES + {"ref", Jim_RefCoreCommand}, + {"getref", Jim_GetrefCoreCommand}, + {"setref", Jim_SetrefCoreCommand}, + {"finalize", Jim_FinalizeCoreCommand}, + {"collect", Jim_CollectCoreCommand}, +#endif + {"rename", Jim_RenameCoreCommand}, + {"dict", Jim_DictCoreCommand}, + {"subst", Jim_SubstCoreCommand}, + {"info", Jim_InfoCoreCommand}, + {"exists", Jim_ExistsCoreCommand}, + {"split", Jim_SplitCoreCommand}, + {"join", Jim_JoinCoreCommand}, + {"format", Jim_FormatCoreCommand}, + {"scan", Jim_ScanCoreCommand}, + {"error", Jim_ErrorCoreCommand}, + {"lrange", Jim_LrangeCoreCommand}, + {"lrepeat", Jim_LrepeatCoreCommand}, + {"env", Jim_EnvCoreCommand}, + {"source", Jim_SourceCoreCommand}, + {"lreverse", Jim_LreverseCoreCommand}, + {"range", Jim_RangeCoreCommand}, + {"rand", Jim_RandCoreCommand}, + {"tailcall", Jim_TailcallCoreCommand}, + {"local", Jim_LocalCoreCommand}, + {"upcall", Jim_UpcallCoreCommand}, + {NULL, NULL}, +}; + +void Jim_RegisterCoreCommands(Jim_Interp *interp) +{ + int i = 0; + + while (Jim_CoreCommandsTable[i].name != NULL) { + Jim_CreateCommand(interp, + Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL); + i++; + } +} + +/* ----------------------------------------------------------------------------- + * Interactive prompt + * ---------------------------------------------------------------------------*/ +void Jim_MakeErrorMessage(Jim_Interp *interp) +{ + Jim_Obj *argv[2]; + + argv[0] = Jim_NewStringObj(interp, "errorInfo", -1); + argv[1] = interp->result; + + Jim_EvalObjVector(interp, 2, argv); +} + +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name) +{ + int count; + char **tablePtrSorted; + int i; + + for (count = 0; tablePtr[count]; count++) { + } + + if (name == NULL) { + name = "option"; + } + + Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); + tablePtrSorted = Jim_Alloc(sizeof(char *) * count); + memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); + qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); + for (i = 0; i < count; i++) { + if (i + 1 == count && count > 1) { + Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); + if (i + 1 != count) { + Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); + } + } + Jim_Free(tablePtrSorted); +} + +int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, + const char *const *tablePtr, int *indexPtr, const char *name, int flags) +{ + const char *bad = "bad "; + const char *const *entryPtr = NULL; + int i; + int match = -1; + int arglen; + const char *arg = Jim_GetString(objPtr, &arglen); + + *indexPtr = -1; + + for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { + if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { + /* Found an exact match */ + *indexPtr = i; + return JIM_OK; + } + if (flags & JIM_ENUM_ABBREV) { + /* Accept an unambiguous abbreviation. + * Note that '-' doesnt' consitute a valid abbreviation + */ + if (strncmp(arg, *entryPtr, arglen) == 0) { + if (*arg == '-' && arglen == 1) { + break; + } + if (match >= 0) { + bad = "ambiguous "; + goto ambiguous; + } + match = i; + } + } + } + + /* If we had an unambiguous partial match */ + if (match >= 0) { + *indexPtr = match; + return JIM_OK; + } + + ambiguous: + if (flags & JIM_ERRMSG) { + JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name); + } + return JIM_ERR; +} + +int Jim_FindByName(const char *name, const char * const array[], size_t len) +{ + int i; + + for (i = 0; i < (int)len; i++) { + if (array[i] && strcmp(array[i], name) == 0) { + return i; + } + } + return -1; +} + +int Jim_IsDict(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &dictObjType; +} + +int Jim_IsList(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &listObjType; +} + +/** + * Very simple printf-like formatting, designed for error messages. + * + * The format may contain up to 5 '%s' or '%#s', corresponding to variable arguments. + * The resulting string is created and set as the result. + * + * Each '%s' should correspond to a regular string parameter. + * Each '%#s' should correspond to a (Jim_Obj *) parameter. + * Any other printf specifier is not allowed (but %% is allowed for the % character). + * + * e.g. Jim_SetResultFormatted(interp, "Bad option \"%#s\" in proc \"%#s\"", optionObjPtr, procNamePtr); + * + * Note: We take advantage of the fact that printf has the same behaviour for both %s and %#s + */ +void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) +{ + /* Initial space needed */ + int len = strlen(format); + int extra = 0; + int n = 0; + const char *params[5]; + char *buf; + va_list args; + int i; + + va_start(args, format); + + for (i = 0; i < len && n < 5; i++) { + int l; + + if (strncmp(format + i, "%s", 2) == 0) { + params[n] = va_arg(args, char *); + + l = strlen(params[n]); + } + else if (strncmp(format + i, "%#s", 3) == 0) { + Jim_Obj *objPtr = va_arg(args, Jim_Obj *); + + params[n] = Jim_GetString(objPtr, &l); + } + else { + if (format[i] == '%') { + i++; + } + continue; + } + n++; + extra += l; + } + + len += extra; + buf = Jim_Alloc(len + 1); + len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); +} + +/* stubs */ +#ifndef jim_ext_package +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) +{ + return JIM_OK; +} +#endif +#ifndef jim_ext_aio +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) +{ + Jim_SetResultString(interp, "aio not enabled", -1); + return NULL; +} +#endif + + +/* + * Local Variables: *** + * c-basic-offset: 4 *** + * tab-width: 4 *** + * End: *** + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.h new file mode 100755 index 0000000..fdc9db9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jim.h @@ -0,0 +1,917 @@ +/* Jim - A small embeddable Tcl interpreter + * + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2005 Clemens Hintze <c.hintze@gmx.net> + * Copyright 2005 patthoyts - Pat Thoyts <patthoyts@users.sf.net> + * Copyright 2008 oharboe - �yvind Harboe - oyvind.harboe@zylin.com + * Copyright 2008 Andrew Lunn <andrew@lunn.ch> + * Copyright 2008 Duane Ellis <openocd@duaneellis.com> + * Copyright 2008 Uwe Klein <uklein@klein-messgeraete.de> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of the Jim Tcl Project. + * + *--- Inline Header File Documentation --- + * [By Duane Ellis, openocd@duaneellis.com, 8/18/8] + * + * Belief is "Jim" would greatly benifit if Jim Internals where + * documented in some way - form whatever, and perhaps - the package: + * 'doxygen' is the correct approach to do that. + * + * Details, see: http://www.stack.nl/~dimitri/doxygen/ + * + * To that end please follow these guide lines: + * + * (A) Document the PUBLIC api in the .H file. + * + * (B) Document JIM Internals, in the .C file. + * + * (C) Remember JIM is embedded in other packages, to that end do + * not assume that your way of documenting is the right way, Jim's + * public documentation should be agnostic, such that it is some + * what agreeable with the "package" that is embedding JIM inside + * of it's own doxygen documentation. + * + * (D) Use minimal Doxygen tags. + * + * This will be an "ongoing work in progress" for some time. + **/ + +#ifndef __JIM__H +#define __JIM__H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <time.h> +#include <limits.h> +#include <stdio.h> /* for the FILE typedef definition */ +#include <stdlib.h> /* In order to export the Jim_Free() macro */ +#include <stdarg.h> /* In order to get type va_list */ + +/* ----------------------------------------------------------------------------- + * System configuration + * autoconf (configure) will set these + * ---------------------------------------------------------------------------*/ +#include <jim-win32compat.h> + +#ifndef HAVE_NO_AUTOCONF +#include <jim-config.h> +#endif + +/* ----------------------------------------------------------------------------- + * Compiler specific fixes. + * ---------------------------------------------------------------------------*/ + +/* Long Long type and related issues */ +#ifndef jim_wide +# ifdef HAVE_LONG_LONG +# define jim_wide long long +# ifndef LLONG_MAX +# define LLONG_MAX 9223372036854775807LL +# endif +# ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# endif +# define JIM_WIDE_MIN LLONG_MIN +# define JIM_WIDE_MAX LLONG_MAX +# else +# define jim_wide long +# define JIM_WIDE_MIN LONG_MIN +# define JIM_WIDE_MAX LONG_MAX +# endif + +/* ----------------------------------------------------------------------------- + * LIBC specific fixes + * ---------------------------------------------------------------------------*/ + +# ifdef HAVE_LONG_LONG +# define JIM_WIDE_MODIFIER "lld" +# else +# define JIM_WIDE_MODIFIER "ld" +# define strtoull strtoul +# endif +#endif + +#define UCHAR(c) ((unsigned char)(c)) + +/* ----------------------------------------------------------------------------- + * Exported defines + * ---------------------------------------------------------------------------*/ + +/* Jim version numbering: every version of jim is marked with a + * successive integer number. This is version 0. The first + * stable version will be 1, then 2, 3, and so on. */ +#define JIM_VERSION 72 + +#define JIM_OK 0 +#define JIM_ERR 1 +#define JIM_RETURN 2 +#define JIM_BREAK 3 +#define JIM_CONTINUE 4 +#define JIM_SIGNAL 5 +#define JIM_EXIT 6 +/* The following are internal codes and should never been seen/used */ +#define JIM_EVAL 7 + +#define JIM_MAX_NESTING_DEPTH 1000 /* default max nesting depth */ + +/* Some function get an integer argument with flags to change + * the behaviour. */ +#define JIM_NONE 0 /* no flags set */ +#define JIM_ERRMSG 1 /* set an error message in the interpreter. */ + +#define JIM_UNSHARED 4 /* Flag to Jim_GetVariable() */ + +/* Flags for Jim_SubstObj() */ +#define JIM_SUBST_NOVAR 1 /* don't perform variables substitutions */ +#define JIM_SUBST_NOCMD 2 /* don't perform command substitutions */ +#define JIM_SUBST_NOESC 4 /* don't perform escapes substitutions */ +#define JIM_SUBST_FLAG 128 /* flag to indicate that this is a real substition object */ + +/* Unused arguments generate annoying warnings... */ +#define JIM_NOTUSED(V) ((void) V) + +/* Flags for Jim_GetEnum() */ +#define JIM_ENUM_ABBREV 2 /* Allow unambiguous abbreviation */ + +/* Flags used by API calls getting a 'nocase' argument. */ +#define JIM_CASESENS 0 /* case sensitive */ +#define JIM_NOCASE 1 /* no case */ + +/* Filesystem related */ +#define JIM_PATH_LEN 1024 + +/* Newline, some embedded system may need -DJIM_CRLF */ +#ifdef JIM_CRLF +#define JIM_NL "\r\n" +#else +#define JIM_NL "\n" +#endif + +#define JIM_LIBPATH "auto_path" +#define JIM_INTERACTIVE "tcl_interactive" + +/* ----------------------------------------------------------------------------- + * Stack + * ---------------------------------------------------------------------------*/ + +typedef struct Jim_Stack { + int len; + int maxlen; + void **vector; +} Jim_Stack; + +/* ----------------------------------------------------------------------------- + * Hash table + * ---------------------------------------------------------------------------*/ + +typedef struct Jim_HashEntry { + const void *key; + union { + void *val; + int intval; + } u; + struct Jim_HashEntry *next; +} Jim_HashEntry; + +typedef struct Jim_HashTableType { + unsigned int (*hashFunction)(const void *key); + const void *(*keyDup)(void *privdata, const void *key); + void *(*valDup)(void *privdata, const void *obj); + int (*keyCompare)(void *privdata, const void *key1, const void *key2); + void (*keyDestructor)(void *privdata, const void *key); + void (*valDestructor)(void *privdata, void *obj); +} Jim_HashTableType; + +typedef struct Jim_HashTable { + Jim_HashEntry **table; + const Jim_HashTableType *type; + unsigned int size; + unsigned int sizemask; + unsigned int used; + unsigned int collisions; + void *privdata; +} Jim_HashTable; + +typedef struct Jim_HashTableIterator { + Jim_HashTable *ht; + int index; + Jim_HashEntry *entry, *nextEntry; +} Jim_HashTableIterator; + +/* This is the initial size of every hash table */ +#define JIM_HT_INITIAL_SIZE 16 + +/* ------------------------------- Macros ------------------------------------*/ +#define Jim_FreeEntryVal(ht, entry) \ + if ((ht)->type->valDestructor) \ + (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) + +#define Jim_SetHashVal(ht, entry, _val_) do { \ + if ((ht)->type->valDup) \ + entry->u.val = (ht)->type->valDup((ht)->privdata, _val_); \ + else \ + entry->u.val = (_val_); \ +} while(0) + +#define Jim_FreeEntryKey(ht, entry) \ + if ((ht)->type->keyDestructor) \ + (ht)->type->keyDestructor((ht)->privdata, (entry)->key) + +#define Jim_SetHashKey(ht, entry, _key_) do { \ + if ((ht)->type->keyDup) \ + entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \ + else \ + entry->key = (_key_); \ +} while(0) + +#define Jim_CompareHashKeys(ht, key1, key2) \ + (((ht)->type->keyCompare) ? \ + (ht)->type->keyCompare((ht)->privdata, key1, key2) : \ + (key1) == (key2)) + +#define Jim_HashKey(ht, key) (ht)->type->hashFunction(key) + +#define Jim_GetHashEntryKey(he) ((he)->key) +#define Jim_GetHashEntryVal(he) ((he)->val) +#define Jim_GetHashTableCollisions(ht) ((ht)->collisions) +#define Jim_GetHashTableSize(ht) ((ht)->size) +#define Jim_GetHashTableUsed(ht) ((ht)->used) + +/* ----------------------------------------------------------------------------- + * Jim_Obj structure + * ---------------------------------------------------------------------------*/ + +/* ----------------------------------------------------------------------------- + * Jim object. This is mostly the same as Tcl_Obj itself, + * with the addition of the 'prev' and 'next' pointers. + * In Jim all the objects are stored into a linked list for GC purposes, + * so that it's possible to access every object living in a given interpreter + * sequentially. When an object is freed, it's moved into a different + * linked list, used as object pool. + * + * The refcount of a freed object is always -1. + * ---------------------------------------------------------------------------*/ +typedef struct Jim_Obj { + int refCount; /* reference count */ + char *bytes; /* string representation buffer. NULL = no string repr. */ + int length; /* number of bytes in 'bytes', not including the numterm. */ + const struct Jim_ObjType *typePtr; /* object type. */ + /* Internal representation union */ + union { + /* integer number type */ + jim_wide wideValue; + /* hashed object type value */ + int hashValue; + /* index type */ + int indexValue; + /* return code type */ + int returnCode; + /* double number type */ + double doubleValue; + /* Generic pointer */ + void *ptr; + /* Generic two pointers value */ + struct { + void *ptr1; + void *ptr2; + } twoPtrValue; + /* Variable object */ + struct { + unsigned jim_wide callFrameId; + struct Jim_Var *varPtr; + } varValue; + /* Command object */ + struct { + unsigned jim_wide procEpoch; + struct Jim_Cmd *cmdPtr; + } cmdValue; + /* List object */ + struct { + struct Jim_Obj **ele; /* Elements vector */ + int len; /* Length */ + int maxLen; /* Allocated 'ele' length */ + } listValue; + /* String type */ + struct { + int maxLength; + int charLength; /* utf-8 char length. -1 if unknown */ + } strValue; + /* Reference type */ + struct { + jim_wide id; + struct Jim_Reference *refPtr; + } refValue; + /* Source type */ + struct { + struct Jim_Obj *fileNameObj; + int lineNumber; + } sourceValue; + /* Dict substitution type */ + struct { + struct Jim_Obj *varNameObjPtr; + struct Jim_Obj *indexObjPtr; + } dictSubstValue; + /* tagged binary type */ + struct { + unsigned char *data; + size_t len; + } binaryValue; + /* Regular expression pattern */ + struct { + unsigned flags; + void *compre; /* really an allocated (regex_t *) */ + } regexpValue; + struct { + int line; + int argc; + } scriptLineValue; + } internalRep; + /* This are 8 or 16 bytes more for every object + * but this is required for efficient garbage collection + * of Jim references. */ + struct Jim_Obj *prevObjPtr; /* pointer to the prev object. */ + struct Jim_Obj *nextObjPtr; /* pointer to the next object. */ +} Jim_Obj; + +/* Jim_Obj related macros */ +#define Jim_IncrRefCount(objPtr) \ + ++(objPtr)->refCount +#define Jim_DecrRefCount(interp, objPtr) \ + if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr) +#define Jim_IsShared(objPtr) \ + ((objPtr)->refCount > 1) + +/* This macro is used when we allocate a new object using + * Jim_New...Obj(), but for some error we need to destroy it. + * Instead to use Jim_IncrRefCount() + Jim_DecrRefCount() we + * can just call Jim_FreeNewObj. To call Jim_Free directly + * seems too raw, the object handling may change and we want + * that Jim_FreeNewObj() can be called only against objects + * that are belived to have refcount == 0. */ +#define Jim_FreeNewObj Jim_FreeObj + +/* Free the internal representation of the object. */ +#define Jim_FreeIntRep(i,o) \ + if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \ + (o)->typePtr->freeIntRepProc(i, o) + +/* Get the internal representation pointer */ +#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr + +/* Set the internal representation pointer */ +#define Jim_SetIntRepPtr(o, p) \ + (o)->internalRep.ptr = (p) + +/* The object type structure. + * There are four methods. + * + * - FreeIntRep is used to free the internal representation of the object. + * Can be NULL if there is nothing to free. + * - DupIntRep is used to duplicate the internal representation of the object. + * If NULL, when an object is duplicated, the internalRep union is + * directly copied from an object to another. + * Note that it's up to the caller to free the old internal repr of the + * object before to call the Dup method. + * - UpdateString is used to create the string from the internal repr. + * - setFromAny is used to convert the current object into one of this type. + */ + +struct Jim_Interp; + +typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *objPtr); +typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); +typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); + +typedef struct Jim_ObjType { + const char *name; /* The name of the type. */ + Jim_FreeInternalRepProc *freeIntRepProc; + Jim_DupInternalRepProc *dupIntRepProc; + Jim_UpdateStringProc *updateStringProc; + int flags; +} Jim_ObjType; + +/* Jim_ObjType flags */ +#define JIM_TYPE_NONE 0 /* No flags */ +#define JIM_TYPE_REFERENCES 1 /* The object may contain referneces. */ + +/* Starting from 1 << 20 flags are reserved for private uses of + * different calls. This way the same 'flags' argument may be used + * to pass both global flags and private flags. */ +#define JIM_PRIV_FLAG_SHIFT 20 + +/* ----------------------------------------------------------------------------- + * Call frame, vars, commands structures + * ---------------------------------------------------------------------------*/ + +/* Call frame */ +typedef struct Jim_CallFrame { + unsigned jim_wide id; /* Call Frame ID. Used for caching. */ + int level; /* Level of this call frame. 0 = global */ + struct Jim_HashTable vars; /* Where local vars are stored */ + struct Jim_HashTable *staticVars; /* pointer to procedure static vars */ + struct Jim_CallFrame *parentCallFrame; + Jim_Obj *const *argv; /* object vector of the current procedure call. */ + int argc; /* number of args of the current procedure call. */ + Jim_Obj *procArgsObjPtr; /* arglist object of the running procedure */ + Jim_Obj *procBodyObjPtr; /* body object of the running procedure */ + struct Jim_CallFrame *nextFramePtr; + Jim_Obj *fileNameObj; /* file and line of caller of this proc (if available) */ + int line; +} Jim_CallFrame; + +/* The var structure. It just holds the pointer of the referenced + * object. If linkFramePtr is not NULL the variable is a link + * to a variable of name store on objPtr living on the given callframe + * (this happens when the [global] or [upvar] command is used). + * The interp in order to always know how to free the Jim_Obj associated + * with a given variable because In Jim objects memory managment is + * bound to interpreters. */ +typedef struct Jim_Var { + Jim_Obj *objPtr; + struct Jim_CallFrame *linkFramePtr; +} Jim_Var; + +/* The cmd structure. */ +typedef int (*Jim_CmdProc)(struct Jim_Interp *interp, int argc, + Jim_Obj *const *argv); +typedef void (*Jim_DelCmdProc)(struct Jim_Interp *interp, void *privData); + + + +/* A command is implemented in C if funcPtr is != NULL, otherwise + * it's a Tcl procedure with the arglist and body represented by the + * two objects referenced by arglistObjPtr and bodyoObjPtr. */ +typedef struct Jim_Cmd { + int inUse; /* Reference count */ + int isproc; /* Is this a procedure? */ + union { + struct { + /* native (C) command */ + Jim_CmdProc cmdProc; /* The command implementation */ + Jim_DelCmdProc delProc; /* Called when the command is deleted if != NULL */ + void *privData; /* command-private data available via Jim_CmdPrivData() */ + } native; + struct { + /* Tcl procedure */ + Jim_Obj *argListObjPtr; + Jim_Obj *bodyObjPtr; + Jim_HashTable *staticVars; /* Static vars hash table. NULL if no statics. */ + struct Jim_Cmd *prevCmd; /* Previous command defn if proc created 'local' */ + int argListLen; /* Length of argListObjPtr */ + int reqArity; /* Number of required parameters */ + int optArity; /* Number of optional parameters */ + int argsPos; /* Position of 'args', if specified, or -1 */ + int upcall; /* True if proc is currently in upcall */ + struct Jim_ProcArg { + Jim_Obj *nameObjPtr; /* Name of this arg */ + Jim_Obj *defaultObjPtr; /* Default value, (or rename for $args) */ + } *arglist; + } proc; + } u; +} Jim_Cmd; + +/* Pseudo Random Number Generator State structure */ +typedef struct Jim_PrngState { + unsigned char sbox[256]; + unsigned int i, j; +} Jim_PrngState; + +/* ----------------------------------------------------------------------------- + * Jim interpreter structure. + * Fields similar to the real Tcl interpreter structure have the same names. + * ---------------------------------------------------------------------------*/ +typedef struct Jim_Interp { + Jim_Obj *result; /* object returned by the last command called. */ + int errorLine; /* Error line where an error occurred. */ + Jim_Obj *errorFileNameObj; /* Error file where an error occurred. */ + int addStackTrace; /* > 0 If a level should be added to the stack trace */ + int maxNestingDepth; /* Used for infinite loop detection. */ + int returnCode; /* Completion code to return on JIM_RETURN. */ + int returnLevel; /* Current level of 'return -level' */ + int exitCode; /* Code to return to the OS on JIM_EXIT. */ + long id; /* Hold unique id for various purposes */ + int signal_level; /* A nesting level of catch -signal */ + jim_wide sigmask; /* Bit mask of caught signals, or 0 if none */ + int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); /* Set a result for the sigmask */ + Jim_CallFrame *framePtr; /* Pointer to the current call frame */ + Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */ + struct Jim_HashTable commands; /* Commands hash table */ + unsigned jim_wide procEpoch; /* Incremented every time the result + of procedures names lookup caching + may no longer be valid. */ + unsigned jim_wide callFrameEpoch; /* Incremented every time a new + callframe is created. This id is used for the + 'ID' field contained in the Jim_CallFrame + structure. */ + int local; /* If 'local' is in effect, newly defined procs keep a reference to the old defn */ + Jim_Obj *liveList; /* Linked list of all the live objects. */ + Jim_Obj *freeList; /* Linked list of all the unused objects. */ + Jim_Obj *currentScriptObj; /* Script currently in execution. */ + Jim_Obj *emptyObj; /* Shared empty string object. */ + Jim_Obj *trueObj; /* Shared true int object. */ + Jim_Obj *falseObj; /* Shared false int object. */ + unsigned jim_wide referenceNextId; /* Next id for reference. */ + struct Jim_HashTable references; /* References hash table. */ + jim_wide lastCollectId; /* reference max Id of the last GC + execution. It's set to -1 while the collection + is running as sentinel to avoid to recursive + calls via the [collect] command inside + finalizers. */ + time_t lastCollectTime; /* unix time of the last GC execution */ + Jim_Obj *stackTrace; /* Stack trace object. */ + Jim_Obj *errorProc; /* Name of last procedure which returned an error */ + Jim_Obj *unknown; /* Unknown command cache */ + int unknown_called; /* The unknown command has been invoked */ + int errorFlag; /* Set if an error occurred during execution. */ + void *cmdPrivData; /* Used to pass the private data pointer to + a command. It is set to what the user specified + via Jim_CreateCommand(). */ + + struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ + struct Jim_HashTable assocData; /* per-interp storage for use by packages */ + Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ + struct Jim_HashTable packages; /* Provided packages hash table */ + Jim_Stack *localProcs; /* procs to be destroyed on end of evaluation */ + Jim_Stack *loadHandles; /* handles of loaded modules [load] */ +} Jim_Interp; + +/* Currently provided as macro that performs the increment. + * At some point may be a real function doing more work. + * The proc epoch is used in order to know when a command lookup + * cached can no longer considered valid. */ +#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ +#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) +#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) +/* Note: Using trueObj and falseObj here makes some things slower...*/ +#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) +#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) +#define Jim_GetResult(i) ((i)->result) +#define Jim_CmdPrivData(i) ((i)->cmdPrivData) +#define Jim_String(o) Jim_GetString((o), NULL) + +/* Note that 'o' is expanded only one time inside this macro, + * so it's safe to use side effects. */ +#define Jim_SetResult(i,o) do { \ + Jim_Obj *_resultObjPtr_ = (o); \ + Jim_IncrRefCount(_resultObjPtr_); \ + Jim_DecrRefCount(i,(i)->result); \ + (i)->result = _resultObjPtr_; \ +} while(0) + +/* Use this for filehandles, etc. which need a unique id */ +#define Jim_GetId(i) (++(i)->id) + +/* Reference structure. The interpreter pointer is held within privdata member in HashTable */ +#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference + string representation must be fixed length. */ +typedef struct Jim_Reference { + Jim_Obj *objPtr; + Jim_Obj *finalizerCmdNamePtr; + char tag[JIM_REFERENCE_TAGLEN+1]; +} Jim_Reference; + +/* ----------------------------------------------------------------------------- + * Exported API prototypes. + * ---------------------------------------------------------------------------*/ + +/* Macros that are common for extensions and core. */ +#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) + +/* The core includes real prototypes, extensions instead + * include a global function pointer for every function exported. + * Once the extension calls Jim_InitExtension(), the global + * functon pointers are set to the value of the STUB table + * contained in the Jim_Interp structure. + * + * This makes Jim able to load extensions even if it is statically + * linked itself, and to load extensions compiled with different + * versions of Jim (as long as the API is still compatible.) */ + +/* Macros are common for core and extensions */ +#define Jim_FreeHashTableIterator(iter) Jim_Free(iter) + +#define JIM_EXPORT + +/* Memory allocation */ +JIM_EXPORT void *Jim_Alloc (int size); +JIM_EXPORT void *Jim_Realloc(void *ptr, int size); +JIM_EXPORT void Jim_Free (void *ptr); +JIM_EXPORT char * Jim_StrDup (const char *s); +JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); + +/* environment */ +JIM_EXPORT char **Jim_GetEnviron(void); +JIM_EXPORT void Jim_SetEnviron(char **env); + +/* evaluation */ +JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); +/* in C code, you can do this and get better error messages */ +/* Jim_EvalSource( interp, __FILE__, __LINE__ , "some tcl commands"); */ +JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); +/* Backwards compatibility */ +#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S)) + +JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script); +JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr); +JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); +JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, + int objc, Jim_Obj *const *objv); +#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov)) +JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr, + Jim_Obj **resObjPtrPtr, int flags); + +/* stack */ +JIM_EXPORT void Jim_InitStack(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack); +JIM_EXPORT int Jim_StackLen(Jim_Stack *stack); +JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element); +JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack); +JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr)); + +/* hash table */ +JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht, + const Jim_HashTableType *type, void *privdata); +JIM_EXPORT int Jim_ExpandHashTable (Jim_HashTable *ht, + unsigned int size); +JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key, + void *val); +JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht, + const void *key, void *val); +JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT int Jim_ResizeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator + (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry + (Jim_HashTableIterator *iter); + +/* objects */ +JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); +JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); +JIM_EXPORT void Jim_InitStringRep (Jim_Obj *objPtr, const char *bytes, + int length); +JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, + int *lenPtr); +JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); + +/* string object */ +JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp, + const char *s, int len); +JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, + const char *s, int charlen); +JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp, + char *s, int len); +JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr, + const char *str, int len); +JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *appendObjPtr); +JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp, + Jim_Obj *objPtr, ...); +JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr); +JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr, + Jim_Obj *objPtr, int nocase); +JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr); +JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp, + Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv); +JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr, + Jim_Obj *fmtObjPtr, int flags); +JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, + Jim_Obj *objPtr, const char *str); +JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, + Jim_Obj *secondObjPtr, int nocase); +JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); + +/* reference object */ +JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, + Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr); + +/* interpreter */ +JIM_EXPORT Jim_Interp * Jim_CreateInterp (void); +JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i); +JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp); +JIM_EXPORT const char *Jim_ReturnCode(int code); +JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...); + +/* commands */ +JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); +JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, + const char *cmdName, Jim_CmdProc cmdProc, void *privData, + Jim_DelCmdProc delProc); +JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, + const char *cmdName); +JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, + const char *oldName, const char *newName); +JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, + Jim_Obj *objPtr, int flags); +JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); +JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, + const char *name, const char *val); +JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, + Jim_CallFrame *targetCallFrame); +JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); + +/* call frame */ +JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, + Jim_Obj *levelObjPtr); + +/* garbage collection */ +JIM_EXPORT int Jim_Collect (Jim_Interp *interp); +JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp); + +/* index object */ +JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr, + int *indexPtr); + +/* list object */ +JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp, + Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec); +JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *objPtr); +JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *appendListPtr); +JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt, + int listindex, Jim_Obj **objPtrPtr, int seterr); +JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, + Jim_Obj *newObjPtr); +JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); + +/* dict object */ +JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj *newObjPtr, int flags); +JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); +JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); +JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); +JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); + +/* return code object */ +JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, + int *intPtr); + +/* expression object */ +JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, + Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); +JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, + Jim_Obj *exprObjPtr, int *boolPtr); + +/* integer object */ +JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, + jim_wide *widePtr); +JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, + long *longPtr); +#define Jim_NewWideObj Jim_NewIntObj +JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, + jim_wide wideValue); + +/* double object */ +JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double *doublePtr); +JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double doubleValue); +JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); + +/* shared strings */ +JIM_EXPORT const char * Jim_GetSharedString (Jim_Interp *interp, + const char *str); +JIM_EXPORT void Jim_ReleaseSharedString (Jim_Interp *interp, + const char *str); + +/* commands utilities */ +JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, + Jim_Obj *const *argv, const char *msg); +JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, + const char * const *tablePtr, int *indexPtr, const char *name, int flags); +JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len, + char *stateCharPtr); +/** + * Find a matching name in the array of the given length. + * + * NULL entries are ignored. + * + * Returns the matching index if found, or -1 if not. + */ +JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); + +/* package utilities */ +typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); +JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); +JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, + Jim_InterpDeleteProc *delProc, void *data); +JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); + +/* Packages C API */ +/* jim-package.c */ +JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, + const char *name, const char *ver, int flags); +JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, + const char *name, int flags); + +/* error messages */ +JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); + +/* interactive mode */ +JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); + +/* Misc */ +JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); +JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); + +/* jim-load.c */ +JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); +JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); + +/* jim-aio.c */ +JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); + + +/* type inspection - avoid where possible */ +JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); +JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); + +#ifdef __cplusplus +} +#endif + +#endif /* __JIM__H */ + +/* + * Local Variables: *** + * c-basic-offset: 4 *** + * tab-width: 4 *** + * End: *** + */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in new file mode 100755 index 0000000..f4eb0e5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimautoconf.h.in @@ -0,0 +1,145 @@ +/* jimautoconf.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Have the dlopen function */ +#undef HAVE_DLOPEN + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if the system has the type `long long'. */ +#undef HAVE_LONG_LONG + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Have libreadline */ +#undef HAVE_READLINE + +/* Define to 1 if you have the `readlink' function. */ +#undef HAVE_READLINK + +/* Define to 1 if you have the `realpath' function. */ +#undef HAVE_REALPATH + +/* Define to 1 if you have the `regcomp' function. */ +#undef HAVE_REGCOMP + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Have libsqlite */ +#undef HAVE_SQLITE + +/* Have libsqlite3 */ +#undef HAVE_SQLITE3 + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strptime' function. */ +#undef HAVE_STRPTIME + +/* Define to 1 if you have the `sysinfo' function. */ +#undef HAVE_SYSINFO + +/* Define to 1 if you have the `syslog' function. */ +#undef HAVE_SYSLOG + +/* Define to 1 if you have the `sys_siglist' function. */ +#undef HAVE_SYS_SIGLIST + +/* Define to 1 if you have the `sys_signame' function. */ +#undef HAVE_SYS_SIGNAME + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <sys/un.h> header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if you have the <termios.h> header file. */ +#undef HAVE_TERMIOS_H + +/* Define to 1 if you have the `ualarm' function. */ +#undef HAVE_UALARM + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the `vfork' function. */ +#undef HAVE_VFORK + +/* Define to 1 if you have the `waitpid' function. */ +#undef HAVE_WAITPID + +/* No need to declare extern 'environ'. */ +#undef NO_ENVIRON_EXTERN + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.c new file mode 100755 index 0000000..c652ad4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.c @@ -0,0 +1,1756 @@ +/* + * regcomp and regexec -- regsub and regerror are elsewhere + * + * Copyright (c) 1986 by University of Toronto. + * Written by Henry Spencer. Not derived from licensed software. + * + * Permission is granted to anyone to use this software for any + * purpose on any computer system, and to redistribute it freely, + * subject to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of + * this software, no matter how awful, even if they arise + * from defects in it. + * + * 2. The origin of this software must not be misrepresented, either + * by explicit claim or by omission. + * + * 3. Altered versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \n as an alternative to | + *** to assist in implementing egrep. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 27 Dec 1986, to add \< and \> for word-matching + *** as in BSD grep and ex. + *** THIS IS AN ALTERED VERSION. It was altered by John Gilmore, + *** hoptoad!gnu, on 28 Dec 1986, to optimize characters quoted with \. + *** THIS IS AN ALTERED VERSION. It was altered by James A. Woods, + *** ames!jaw, on 19 June 1987, to quash a regcomp() redundancy. + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@vix.com, on 28 August 1993, for use in jam. Regmagic.h + *** was moved into regexp.h, and the include of regexp.h now uses "'s + *** to avoid conflicting with the system regexp.h. Const, bless its + *** soul, was removed so it can compile everywhere. The declaration + *** of strchr() was in conflict on AIX, so it was removed (as it is + *** happily defined in string.h). + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@perforce.com, on 20 January 2000, to use function prototypes. + *** THIS IS AN ALTERED VERSION. It was altered by Christopher Seiwald + *** seiwald@perforce.com, on 05 November 2002, to const string literals. + * + * THIS IS AN ALTERED VERSION. It was altered by Steve Bennett <steveb@workware.net.au> + * on 16 October 2010, to remove static state and add better Tcl ARE compatibility. + * This includes counted repetitions, UTF-8 support, character classes, + * shorthand character classes, increased number of parentheses to 100, + * backslash escape sequences. It also removes \n as an alternative to |. + * + * Beware that some of this code is subtly aware of the way operator + * precedence is structured in regular expressions. Serious changes in + * regular-expression syntax might require a total rethink. + */ +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" +#include "jimregexp.h" +#include "utf8.h" + +#if !defined(HAVE_REGCOMP) || defined(JIM_REGEXP) + +/* + * Structure for regexp "program". This is essentially a linear encoding + * of a nondeterministic finite-state machine (aka syntax charts or + * "railroad normal form" in parsing technology). Each node is an opcode + * plus a "next" pointer, possibly plus an operand. "Next" pointers of + * all nodes except BRANCH implement concatenation; a "next" pointer with + * a BRANCH on both ends of it is connecting two alternatives. (Here we + * have one of the subtle syntax dependencies: an individual BRANCH (as + * opposed to a collection of them) is never concatenated with anything + * because of operator precedence.) The operand of some types of node is + * a literal string; for others, it is a node leading into a sub-FSM. In + * particular, the operand of a BRANCH node is the first node of the branch. + * (NB this is *not* a tree structure: the tail of the branch connects + * to the thing following the set of BRANCHes.) The opcodes are: + */ + +/* This *MUST* be less than (255-20)/2=117 */ +#define REG_MAX_PAREN 100 + +/* definition number opnd? meaning */ +#define END 0 /* no End of program. */ +#define BOL 1 /* no Match "" at beginning of line. */ +#define EOL 2 /* no Match "" at end of line. */ +#define ANY 3 /* no Match any one character. */ +#define ANYOF 4 /* str Match any character in this string. */ +#define ANYBUT 5 /* str Match any character not in this string. */ +#define BRANCH 6 /* node Match this alternative, or the next... */ +#define BACK 7 /* no Match "", "next" ptr points backward. */ +#define EXACTLY 8 /* str Match this string. */ +#define NOTHING 9 /* no Match empty string. */ +#define REP 10 /* max,min Match this (simple) thing [min,max] times. */ +#define REPMIN 11 /* max,min Match this (simple) thing [min,max] times, mininal match. */ +#define REPX 12 /* max,min Match this (complex) thing [min,max] times. */ +#define REPXMIN 13 /* max,min Match this (complex) thing [min,max] times, minimal match. */ + +#define WORDA 15 /* no Match "" at wordchar, where prev is nonword */ +#define WORDZ 16 /* no Match "" at nonwordchar, where prev is word */ +#define OPEN 20 /* no Mark this point in input as start of #n. */ + /* OPEN+1 is number 1, etc. */ +#define CLOSE (OPEN+REG_MAX_PAREN) /* no Analogous to OPEN. */ +#define CLOSE_END (CLOSE+REG_MAX_PAREN) + +/* + * The first byte of the regexp internal "program" is actually this magic + * number; the start node begins in the second byte. + */ +#define REG_MAGIC 0xFADED00D + +/* + * Opcode notes: + * + * BRANCH The set of branches constituting a single choice are hooked + * together with their "next" pointers, since precedence prevents + * anything being concatenated to any individual branch. The + * "next" pointer of the last BRANCH in a choice points to the + * thing following the whole choice. This is also where the + * final "next" pointer of each individual branch points; each + * branch starts with the operand node of a BRANCH node. + * + * BACK Normal "next" pointers all implicitly point forward; BACK + * exists to make loop structures possible. + * + * STAR,PLUS '?', and complex '*' and '+', are implemented as circular + * BRANCH structures using BACK. Simple cases (one character + * per match) are implemented with STAR and PLUS for speed + * and to minimize recursive plunges. + * + * OPEN,CLOSE ...are numbered at compile time. + */ + +/* + * A node is one char of opcode followed by two chars of "next" pointer. + * "Next" pointers are stored as two 8-bit pieces, high order first. The + * value is a positive offset from the opcode of the node containing it. + * An operand, if any, simply follows the node. (Note that much of the + * code generation knows about this implicit relationship.) + * + * Using two bytes for the "next" pointer is vast overkill for most things, + * but allows patterns to get big without disasters. + */ +#define OP(preg, p) (preg->program[p]) +#define NEXT(preg, p) (preg->program[p + 1]) +#define OPERAND(p) ((p) + 2) + +/* + * See regmagic.h for one further detail of program structure. + */ + + +/* + * Utility definitions. + */ + +#define FAIL(R,M) { (R)->err = (M); return (M); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') +#define META "^$.[()|?{+*" + +/* + * Flags to be passed up and down. + */ +#define HASWIDTH 01 /* Known never to match null string. */ +#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */ +#define SPSTART 04 /* Starts with * or +. */ +#define WORST 0 /* Worst case. */ + +#define MAX_REP_COUNT 1000000 + +/* + * Forward declarations for regcomp()'s friends. + */ +static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp ); +static int regpiece(regex_t *preg, int *flagp ); +static int regbranch(regex_t *preg, int *flagp ); +static int regatom(regex_t *preg, int *flagp ); +static int regnode(regex_t *preg, int op ); +static int regnext(regex_t *preg, int p ); +static void regc(regex_t *preg, int b ); +static int reginsert(regex_t *preg, int op, int size, int opnd ); +static void regtail_(regex_t *preg, int p, int val, int line ); +static void regoptail(regex_t *preg, int p, int val ); +#define regtail(PREG, P, VAL) regtail_(PREG, P, VAL, __LINE__) + +static int reg_range_find(const int *string, int c); +static const char *str_find(const char *string, int c, int nocase); +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); + +/*#define DEBUG*/ +#ifdef DEBUG +int regnarrate = 0; +static void regdump(regex_t *preg); +static const char *regprop( int op ); +#endif + + +/** + * Returns the length of the null-terminated integer sequence. + */ +static int str_int_len(const int *seq) +{ + int n = 0; + while (*seq++) { + n++; + } + return n; +} + +/* + - regcomp - compile a regular expression into internal code + * + * We can't allocate space until we know how big the compiled form will be, + * but we can't compile it (and thus know how big it is) until we've got a + * place to put the code. So we cheat: we compile it twice, once with code + * generation turned off and size counting turned on, and once "for real". + * This also means that we don't allocate space until we are sure that the + * thing really will compile successfully, and we never have to move the + * code and thus invalidate pointers into it. (Note that it has to be in + * one piece because free() must be able to free it all.) + * + * Beware that the optimization-preparation code in here knows about some + * of the structure of the compiled regexp. + */ +int regcomp(regex_t *preg, const char *exp, int cflags) +{ + int scan; + int longest; + unsigned len; + int flags; + +#ifdef DEBUG + fprintf(stderr, "Compiling: '%s'\n", exp); +#endif + memset(preg, 0, sizeof(*preg)); + + if (exp == NULL) + FAIL(preg, REG_ERR_NULL_ARGUMENT); + + /* First pass: determine size, legality. */ + preg->cflags = cflags; + preg->regparse = exp; + /* XXX: For now, start unallocated */ + preg->program = NULL; + preg->proglen = 0; + +#if 1 + /* Allocate space. */ + preg->proglen = (strlen(exp) + 1) * 5; + preg->program = malloc(preg->proglen * sizeof(int)); + if (preg->program == NULL) + FAIL(preg, REG_ERR_NOMEM); +#endif + + /* Note that since we store a magic value as the first item in the program, + * program offsets will never be 0 + */ + regc(preg, REG_MAGIC); + if (reg(preg, 0, &flags) == 0) { + return preg->err; + } + + /* Small enough for pointer-storage convention? */ + if (preg->re_nsub >= REG_MAX_PAREN) /* Probably could be 65535L. */ + FAIL(preg,REG_ERR_TOO_BIG); + + /* Dig out information for optimizations. */ + preg->regstart = 0; /* Worst-case defaults. */ + preg->reganch = 0; + preg->regmust = 0; + preg->regmlen = 0; + scan = 1; /* First BRANCH. */ + if (OP(preg, regnext(preg, scan)) == END) { /* Only one top-level choice. */ + scan = OPERAND(scan); + + /* Starting-point info. */ + if (OP(preg, scan) == EXACTLY) { + preg->regstart = preg->program[OPERAND(scan)]; + } + else if (OP(preg, scan) == BOL) + preg->reganch++; + + /* + * If there's something expensive in the r.e., find the + * longest literal string that must appear and make it the + * regmust. Resolve ties in favor of later strings, since + * the regstart check works with the beginning of the r.e. + * and avoiding duplication strengthens checking. Not a + * strong reason, but sufficient in the absence of others. + */ + if (flags&SPSTART) { + longest = 0; + len = 0; + for (; scan != 0; scan = regnext(preg, scan)) { + if (OP(preg, scan) == EXACTLY) { + int plen = str_int_len(preg->program + OPERAND(scan)); + if (plen >= len) { + longest = OPERAND(scan); + len = plen; + } + } + } + preg->regmust = longest; + preg->regmlen = len; + } + } + +#ifdef DEBUG + regdump(preg); +#endif + + return 0; +} + +/* + - reg - regular expression, i.e. main body or parenthesized thing + * + * Caller must absorb opening parenthesis. + * + * Combining parenthesis handling with the base level of regular expression + * is a trifle forced, but the need to tie the tails of the branches to what + * follows makes it hard to avoid. + */ +static int reg(regex_t *preg, int paren /* Parenthesized? */, int *flagp ) +{ + int ret; + int br; + int ender; + int parno = 0; + int flags; + + *flagp = HASWIDTH; /* Tentatively. */ + + /* Make an OPEN node, if parenthesized. */ + if (paren) { + parno = ++preg->re_nsub; + ret = regnode(preg, OPEN+parno); + } else + ret = 0; + + /* Pick up the branches, linking them together. */ + br = regbranch(preg, &flags); + if (br == 0) + return 0; + if (ret != 0) + regtail(preg, ret, br); /* OPEN -> first. */ + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*preg->regparse == '|') { + preg->regparse++; + br = regbranch(preg, &flags); + if (br == 0) + return 0; + regtail(preg, ret, br); /* BRANCH -> BRANCH. */ + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + /* Make a closing node, and hook it on the end. */ + ender = regnode(preg, (paren) ? CLOSE+parno : END); + regtail(preg, ret, ender); + + /* Hook the tails of the branches to the closing node. */ + for (br = ret; br != 0; br = regnext(preg, br)) + regoptail(preg, br, ender); + + /* Check for proper termination. */ + if (paren && *preg->regparse++ != ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else if (!paren && *preg->regparse != '\0') { + if (*preg->regparse == ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else { + preg->err = REG_ERR_JUNK_ON_END; + return 0; + } + } + + return(ret); +} + +/* + - regbranch - one alternative of an | operator + * + * Implements the concatenation operator. + */ +static int regbranch(regex_t *preg, int *flagp ) +{ + int ret; + int chain; + int latest; + int flags; + + *flagp = WORST; /* Tentatively. */ + + ret = regnode(preg, BRANCH); + chain = 0; + while (*preg->regparse != '\0' && *preg->regparse != ')' && + *preg->regparse != '|') { + latest = regpiece(preg, &flags); + if (latest == 0) + return 0; + *flagp |= flags&HASWIDTH; + if (chain == 0) {/* First piece. */ + *flagp |= flags&SPSTART; + } + else { + regtail(preg, chain, latest); + } + chain = latest; + } + if (chain == 0) /* Loop ran zero times. */ + (void) regnode(preg, NOTHING); + + return(ret); +} + +/* + - regpiece - something followed by possible [*+?] + * + * Note that the branching code sequences used for ? and the general cases + * of * and + are somewhat optimized: they use the same NOTHING node as + * both the endmarker for their branch list and the body of the last branch. + * It might seem that this node could be dispensed with entirely, but the + * endmarker role is not redundant. + */ +static int regpiece(regex_t *preg, int *flagp) +{ + int ret; + char op; + int next; + int flags; + int chain = 0; + int min; + int max; + + ret = regatom(preg, &flags); + if (ret == 0) + return 0; + + op = *preg->regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') { + preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; + return 0; + } + + /* Handle braces (counted repetition) by expansion */ + if (op == '{') { + char *end; + + min = strtoul(preg->regparse + 1, &end, 10); + if (end == preg->regparse + 1) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (*end == '}') { + max = min; + } + else { + preg->regparse = end; + max = strtoul(preg->regparse + 1, &end, 10); + if (*end != '}') { + preg->err = REG_ERR_UNMATCHED_BRACES; + return 0; + } + } + if (end == preg->regparse + 1) { + max = MAX_REP_COUNT; + } + else if (max < min || max >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (min >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + + preg->regparse = strchr(preg->regparse, '}'); + } + else { + min = (op == '+'); + max = (op == '?' ? 1 : MAX_REP_COUNT); + } + + if (preg->regparse[1] == '?') { + preg->regparse++; + next = reginsert(preg, flags & SIMPLE ? REPMIN : REPXMIN, 5, ret); + } + else { + next = reginsert(preg, flags & SIMPLE ? REP: REPX, 5, ret); + } + preg->program[ret + 2] = max; + preg->program[ret + 3] = min; + preg->program[ret + 4] = 0; + + *flagp = (min) ? (WORST|HASWIDTH) : (WORST|SPSTART); + + if (!(flags & SIMPLE)) { + int back = regnode(preg, BACK); + regtail(preg, back, ret); + regtail(preg, next, back); + } + + preg->regparse++; + if (ISMULT(*preg->regparse)) { + preg->err = REG_ERR_NESTED_COUNT; + return 0; + } + + return chain ? chain : ret; +} + +/** + * Add all characters in the inclusive range between lower and upper. + * + * Handles a swapped range (upper < lower). + */ +static void reg_addrange(regex_t *preg, int lower, int upper) +{ + if (lower > upper) { + reg_addrange(preg, upper, lower); + } + /* Add a range as length, start */ + regc(preg, upper - lower + 1); + regc(preg, lower); +} + +/** + * Add a null-terminated literal string as a set of ranges. + */ +static void reg_addrange_str(regex_t *preg, const char *str) +{ + while (*str) { + reg_addrange(preg, *str, *str); + str++; + } +} + +/** + * Extracts the next unicode char from utf8. + * + * If 'upper' is set, converts the char to uppercase. + */ +static int reg_utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + +/** + * Converts a hex digit to decimal. + * + * Returns -1 for an invalid hex digit. + */ +static int hexdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +/** + * Parses up to 'n' hex digits at 's' and stores the result in *uc. + * + * Returns the number of hex digits parsed. + * If there are no hex digits, returns 0 and stores nothing. + */ +static int parse_hex(const char *s, int n, int *uc) +{ + int val = 0; + int k; + + for (k = 0; k < n; k++) { + int c = hexdigitval(*s++); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + if (k) { + *uc = val; + } + return k; +} + +/** + * Call for chars after a backlash to decode the escape sequence. + * + * Stores the result in *ch. + * + * Returns the number of bytes consumed. + */ +static int reg_decode_escape(const char *s, int *ch) +{ + int n; + const char *s0 = s; + + *ch = *s++; + + switch (*ch) { + case 'b': *ch = '\b'; break; + case 'e': *ch = 27; break; + case 'f': *ch = '\f'; break; + case 'n': *ch = '\n'; break; + case 'r': *ch = '\r'; break; + case 't': *ch = '\t'; break; + case 'v': *ch = '\v'; break; + case 'u': + if ((n = parse_hex(s, 4, ch)) > 0) { + s += n; + } + break; + case 'x': + if ((n = parse_hex(s, 2, ch)) > 0) { + s += n; + } + break; + case '\0': + s--; + *ch = '\\'; + break; + } + return s - s0; +} + +/* + - regatom - the lowest level + * + * Optimization: gobbles an entire sequence of ordinary characters so that + * it can turn them into a single node, which is smaller to store and + * faster to run. Backslashed characters are exceptions, each becoming a + * separate node; the code is simpler that way and it's not worth fixing. + */ +static int regatom(regex_t *preg, int *flagp) +{ + int ret; + int flags; + int nocase = (preg->cflags & REG_ICASE); + + int ch; + int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); + + *flagp = WORST; /* Tentatively. */ + + preg->regparse += n; + switch (ch) { + /* FIXME: these chars only have meaning at beg/end of pat? */ + case '^': + ret = regnode(preg, BOL); + break; + case '$': + ret = regnode(preg, EOL); + break; + case '.': + ret = regnode(preg, ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + const char *pattern = preg->regparse; + + if (*pattern == '^') { /* Complement of range. */ + ret = regnode(preg, ANYBUT); + pattern++; + } else + ret = regnode(preg, ANYOF); + + /* Special case. If the first char is ']' or '-', it is part of the set */ + if (*pattern == ']' || *pattern == '-') { + reg_addrange(preg, *pattern, *pattern); + pattern++; + } + + while (*pattern && *pattern != ']') { + /* Is this a range? a-z */ + int start; + int end; + + pattern += reg_utf8_tounicode_case(pattern, &start, nocase); + if (start == '\\') { + pattern += reg_decode_escape(pattern, &start); + if (start == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + if (pattern[0] == '-' && pattern[1]) { + /* skip '-' */ + pattern += utf8_tounicode(pattern, &end); + pattern += reg_utf8_tounicode_case(pattern, &end, nocase); + if (end == '\\') { + pattern += reg_decode_escape(pattern, &end); + if (end == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + reg_addrange(preg, start, end); + continue; + } + if (start == '[') { + if (strncmp(pattern, ":alpha:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":alnum:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":space:]", 8) == 0) { + reg_addrange_str(preg, " \t\r\n\f\v"); + pattern += 8; + continue; + } + } + /* Not a range, so just add the char */ + reg_addrange(preg, start, start); + } + regc(preg, '\0'); + + if (*pattern) { + pattern++; + } + preg->regparse = pattern; + + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(preg, 1, &flags); + if (ret == 0) + return 0; + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + preg->err = REG_ERR_INTERNAL; + return 0; /* Supposed to be caught earlier. */ + case '?': + case '+': + case '*': + case '{': + preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; + return 0; + case '\\': + switch (*preg->regparse++) { + case '\0': + preg->err = REG_ERR_TRAILING_BACKSLASH; + return 0; + case '<': + case 'm': + ret = regnode(preg, WORDA); + break; + case '>': + case 'M': + ret = regnode(preg, WORDZ); + break; + case 'd': + ret = regnode(preg, ANYOF); + reg_addrange(preg, '0', '9'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 'w': + ret = regnode(preg, ANYOF); + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + reg_addrange(preg, '_', '_'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 's': + ret = regnode(preg, ANYOF); + reg_addrange_str(preg," \t\r\n\f\v"); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + /* FIXME: Someday handle \1, \2, ... */ + default: + /* Handle general quoted chars in exact-match routine */ + /* Back up to include the backslash */ + preg->regparse--; + goto de_fault; + } + break; + de_fault: + default: { + /* + * Encode a string of characters to be matched exactly. + */ + int added = 0; + + /* Back up to pick up the first char of interest */ + preg->regparse -= n; + + ret = regnode(preg, EXACTLY); + + /* Note that a META operator such as ? or * consumes the + * preceding char. + * Thus we must be careful to look ahead by 2 and add the + * last char as it's own EXACTLY if necessary + */ + + /* Until end of string or a META char is reached */ + while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { + n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); + if (ch == '\\' && preg->regparse[n]) { + /* Non-trailing backslash. + * Is this a special escape, or a regular escape? + */ + if (strchr("<>mMwds", preg->regparse[n])) { + /* A special escape. All done with EXACTLY */ + break; + } + /* Decode it. Note that we add the length for the escape + * sequence to the length for the backlash so we can skip + * the entire sequence, or not as required. + */ + n += reg_decode_escape(preg->regparse + n, &ch); + if (ch == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + /* Now we have one char 'ch' of length 'n'. + * Check to see if the following char is a MULT + */ + + if (ISMULT(preg->regparse[n])) { + /* Yes. But do we already have some EXACTLY chars? */ + if (added) { + /* Yes, so return what we have and pick up the current char next time around */ + break; + } + /* No, so add this single char and finish */ + regc(preg, ch); + added++; + preg->regparse += n; + break; + } + + /* No, so just add this char normally */ + regc(preg, ch); + added++; + preg->regparse += n; + } + regc(preg, '\0'); + + *flagp |= HASWIDTH; + if (added == 1) + *flagp |= SIMPLE; + break; + } + break; + } + + return(ret); +} + +static void reg_grow(regex_t *preg, int n) +{ + if (preg->p + n >= preg->proglen) { + preg->proglen = (preg->p + n) * 2; + preg->program = realloc(preg->program, preg->proglen * sizeof(int)); + } +} + +/* + - regnode - emit a node + */ +/* Location. */ +static int regnode(regex_t *preg, int op) +{ + reg_grow(preg, 2); + + preg->program[preg->p++] = op; + preg->program[preg->p++] = 0; + + /* Return the start of the node */ + return preg->p - 2; +} + +/* + - regc - emit (if appropriate) a byte of code + */ +static void regc(regex_t *preg, int b ) +{ + reg_grow(preg, 1); + preg->program[preg->p++] = b; +} + +/* + - reginsert - insert an operator in front of already-emitted operand + * + * Means relocating the operand. + * Returns the new location of the original operand. + */ +static int reginsert(regex_t *preg, int op, int size, int opnd ) +{ + reg_grow(preg, size); + + /* Move everything from opnd up */ + memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); + /* Zero out the new space */ + memset(preg->program + opnd, 0, sizeof(int) * size); + + preg->program[opnd] = op; + + preg->p += size; + + return opnd + size; +} + +/* + - regtail - set the next-pointer at the end of a node chain + */ +static void regtail_(regex_t *preg, int p, int val, int line ) +{ + int scan; + int temp; + int offset; + + /* Find last node. */ + scan = p; + for (;;) { + temp = regnext(preg, scan); + if (temp == 0) + break; + scan = temp; + } + + if (OP(preg, scan) == BACK) + offset = scan - val; + else + offset = val - scan; + + preg->program[scan + 1] = offset; +} + +/* + - regoptail - regtail on operand of first argument; nop if operandless + */ + +static void regoptail(regex_t *preg, int p, int val ) +{ + /* "Operandless" and "op != BRANCH" are synonymous in practice. */ + if (p != 0 && OP(preg, p) == BRANCH) { + regtail(preg, OPERAND(p), val); + } +} + +/* + * regexec and friends + */ + +/* + * Forwards. + */ +static int regtry(regex_t *preg, const char *string ); +static int regmatch(regex_t *preg, int prog); +static int regrepeat(regex_t *preg, int p, int max); + +/* + - regexec - match a regexp against a string + */ +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) +{ + const char *s; + int scan; + + /* Be paranoid... */ + if (preg == NULL || preg->program == NULL || string == NULL) { + return REG_ERR_NULL_ARGUMENT; + } + + /* Check validity of program. */ + if (*preg->program != REG_MAGIC) { + return REG_ERR_CORRUPTED; + } + +#ifdef DEBUG + fprintf(stderr, "regexec: %s\n", string); + regdump(preg); +#endif + + preg->eflags = eflags; + preg->pmatch = pmatch; + preg->nmatch = nmatch; + preg->start = string; /* All offsets are computed from here */ + + /* Must clear out the embedded repeat counts */ + for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) { + switch (OP(preg, scan)) { + case REP: + case REPMIN: + case REPX: + case REPXMIN: + preg->program[scan + 4] = 0; + break; + } + } + + /* If there is a "must appear" string, look for it. */ + if (preg->regmust != 0) { + s = string; + while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { + if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { + break; + } + s++; + } + if (s == NULL) /* Not present. */ + return REG_NOMATCH; + } + + /* Mark beginning of line for ^ . */ + preg->regbol = string; + + /* Simplest case: anchored match need be tried only once (maybe per line). */ + if (preg->reganch) { + if (eflags & REG_NOTBOL) { + /* This is an anchored search, but not an BOL, so possibly skip to the next line */ + goto nextline; + } + while (1) { + int ret = regtry(preg, string); + if (ret) { + return REG_NOERROR; + } + if (*string) { +nextline: + if (preg->cflags & REG_NEWLINE) { + /* Try the next anchor? */ + string = strchr(string, '\n'); + if (string) { + preg->regbol = ++string; + continue; + } + } + } + return REG_NOMATCH; + } + } + + /* Messy cases: unanchored match. */ + s = string; + if (preg->regstart != '\0') { + /* We know what char it must start with. */ + while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { + if (regtry(preg, s)) + return REG_NOERROR; + s++; + } + } + else + /* We don't -- general case. */ + while (1) { + if (regtry(preg, s)) + return REG_NOERROR; + if (*s == '\0') { + break; + } + s += utf8_charlen(*s); + } + + /* Failure. */ + return REG_NOMATCH; +} + +/* + - regtry - try match at specific point + */ + /* 0 failure, 1 success */ +static int regtry( regex_t *preg, const char *string ) +{ + int i; + + preg->reginput = string; + + for (i = 0; i < preg->nmatch; i++) { + preg->pmatch[i].rm_so = -1; + preg->pmatch[i].rm_eo = -1; + } + if (regmatch(preg, 1)) { + preg->pmatch[0].rm_so = string - preg->start; + preg->pmatch[0].rm_eo = preg->reginput - preg->start; + return(1); + } else + return(0); +} + +/** + * Returns bytes matched if 'pattern' is a prefix of 'string'. + * + * If 'nocase' is non-zero, does a case-insensitive match. + * + * Returns -1 on not found. + */ +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase) +{ + const char *s = string; + while (proglen && *s) { + int ch; + int n = reg_utf8_tounicode_case(s, &ch, nocase); + if (ch != *prog) { + return -1; + } + prog++; + s += n; + proglen--; + } + if (proglen == 0) { + return s - string; + } + return -1; +} + +/** + * Searchs for 'c' in the range 'range'. + * + * Returns 1 if found, or 0 if not. + */ +static int reg_range_find(const int *range, int c) +{ + while (*range) { + /*printf("Checking %d in range [%d,%d]\n", c, range[1], (range[0] + range[1] - 1));*/ + if (c >= range[1] && c <= (range[0] + range[1] - 1)) { + return 1; + } + range += 2; + } + return 0; +} + +/** + * Search for the character 'c' in the utf-8 string 'string'. + * + * If 'nocase' is set, the 'string' is assumed to be uppercase + * and 'c' is converted to uppercase before matching. + * + * Returns the byte position in the string where the 'c' was found, or + * NULL if not found. + */ +static const char *str_find(const char *string, int c, int nocase) +{ + if (nocase) { + /* The "string" should already be converted to uppercase */ + c = utf8_upper(c); + } + while (*string) { + int ch; + int n = reg_utf8_tounicode_case(string, &ch, nocase); + if (c == ch) { + return string; + } + string += n; + } + return NULL; +} + +/** + * Returns true if 'ch' is an end-of-line char. + * + * In REG_NEWLINE mode, \n is considered EOL in + * addition to \0 + */ +static int reg_iseol(regex_t *preg, int ch) +{ + if (preg->cflags & REG_NEWLINE) { + return ch == '\0' || ch == '\n'; + } + else { + return ch == '\0'; + } +} + +static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin) +{ + int nextch = '\0'; + const char *save; + int no; + int c; + + int max = preg->program[scan + 2]; + int min = preg->program[scan + 3]; + int next = regnext(preg, scan); + + /* + * Lookahead to avoid useless match attempts + * when we know what character comes next. + */ + if (OP(preg, next) == EXACTLY) { + nextch = preg->program[OPERAND(next)]; + } + save = preg->reginput; + no = regrepeat(preg, scan + 5, max); + if (no < min) { + return 0; + } + if (matchmin) { + /* from min up to no */ + max = no; + no = min; + } + /* else from no down to min */ + while (1) { + if (matchmin) { + if (no > max) { + break; + } + } + else { + if (no < min) { + break; + } + } + preg->reginput = save + utf8_index(save, no); + reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + /* If it could work, try it. */ + if (reg_iseol(preg, nextch) || c == nextch) { + if (regmatch(preg, next)) { + return(1); + } + } + if (matchmin) { + /* Couldn't or didn't, add one more */ + no++; + } + else { + /* Couldn't or didn't -- back up. */ + no--; + } + } + return(0); +} + +static int regmatchrepeat(regex_t *preg, int scan, int matchmin) +{ + int *scanpt = preg->program + scan; + + int max = scanpt[2]; + int min = scanpt[3]; + + /* Have we reached min? */ + if (scanpt[4] < min) { + /* No, so get another one */ + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + if (scanpt[4] > max) { + return 0; + } + + if (matchmin) { + /* minimal, so try other branch first */ + if (regmatch(preg, regnext(preg, scan))) { + return 1; + } + /* No, so try one more */ + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + /* maximal, so try this branch again */ + if (scanpt[4] < max) { + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + } + /* At this point we are at max with no match. Try the other branch */ + return regmatch(preg, regnext(preg, scan)); +} + +/* + - regmatch - main matching routine + * + * Conceptually the strategy is simple: check to see whether the current + * node matches, call self recursively to see whether the rest matches, + * and then act accordingly. In practice we make some effort to avoid + * recursion, in particular by going through "ordinary" nodes (that don't + * need to know whether the rest of the match failed) by a loop instead of + * by recursion. + */ +/* 0 failure, 1 success */ +static int regmatch(regex_t *preg, int prog) +{ + int scan; /* Current node. */ + int next; /* Next node. */ + + scan = prog; + +#ifdef DEBUG + if (scan != 0 && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != 0) { + int n; + int c; +#ifdef DEBUG + if (regnarrate) { + fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); /* Where, what. */ + } +#endif + next = regnext(preg, scan); + n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + + switch (OP(preg, scan)) { + case BOL: + if (preg->reginput != preg->regbol) + return(0); + break; + case EOL: + if (!reg_iseol(preg, c)) { + return(0); + } + break; + case WORDA: + /* Must be looking at a letter, digit, or _ */ + if ((!isalnum(UCHAR(c))) && c != '_') + return(0); + /* Prev must be BOL or nonword */ + if (preg->reginput > preg->regbol && + (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) + return(0); + break; + case WORDZ: + /* Can't match at BOL */ + if (preg->reginput > preg->regbol) { + /* Current must be EOL or nonword */ + if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { + c = preg->reginput[-1]; + /* Previous must be word */ + if (isalnum(UCHAR(c)) || c == '_') { + break; + } + } + } + /* No */ + return(0); + + case ANY: + if (reg_iseol(preg, c)) + return 0; + preg->reginput += n; + break; + case EXACTLY: { + int opnd; + int len; + int slen; + + opnd = OPERAND(scan); + len = str_int_len(preg->program + opnd); + + slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE); + if (slen < 0) { + return(0); + } + preg->reginput += slen; + } + break; + case ANYOF: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) { + return(0); + } + preg->reginput += n; + break; + case ANYBUT: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) { + return(0); + } + preg->reginput += n; + break; + case NOTHING: + break; + case BACK: + break; + case BRANCH: { + const char *save; + + if (OP(preg, next) != BRANCH) /* No choice. */ + next = OPERAND(scan); /* Avoid recursion. */ + else { + do { + save = preg->reginput; + if (regmatch(preg, OPERAND(scan))) { + return(1); + } + preg->reginput = save; + scan = regnext(preg, scan); + } while (scan != 0 && OP(preg, scan) == BRANCH); + return(0); + /* NOTREACHED */ + } + } + break; + case REP: + case REPMIN: + return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); + + case REPX: + case REPXMIN: + return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); + + case END: + return(1); /* Success! */ + break; + default: + if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { + const char *save; + + save = preg->reginput; + + if (regmatch(preg, next)) { + int no; + /* + * Don't set startp if some later + * invocation of the same parentheses + * already has. + */ + if (OP(preg, scan) < CLOSE) { + no = OP(preg, scan) - OPEN; + if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { + preg->pmatch[no].rm_so = save - preg->start; + } + } + else { + no = OP(preg, scan) - CLOSE; + if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { + preg->pmatch[no].rm_eo = save - preg->start; + } + } + return(1); + } else + return(0); + } + return REG_ERR_INTERNAL; + } + + scan = next; + } + + /* + * We get here only if there's trouble -- normally "case END" is + * the terminating point. + */ + return REG_ERR_INTERNAL; +} + +/* + - regrepeat - repeatedly match something simple, report how many + */ +static int regrepeat(regex_t *preg, int p, int max) +{ + int count = 0; + const char *scan; + int opnd; + int ch; + int n; + + scan = preg->reginput; + opnd = OPERAND(p); + switch (OP(preg, p)) { + case ANY: + /* No need to handle utf8 specially here */ + while (!reg_iseol(preg, *scan) && count < max) { + count++; + scan++; + } + break; + case EXACTLY: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (preg->program[opnd] != ch) { + break; + } + count++; + scan += n; + } + break; + case ANYOF: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) == 0) { + break; + } + count++; + scan += n; + } + break; + case ANYBUT: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) != 0) { + break; + } + count++; + scan += n; + } + break; + default: /* Oh dear. Called inappropriately. */ + preg->err = REG_ERR_INTERNAL; + count = 0; /* Best compromise. */ + break; + } + preg->reginput = scan; + + return(count); +} + +/* + - regnext - dig the "next" pointer out of a node + */ +static int regnext(regex_t *preg, int p ) +{ + int offset; + + offset = NEXT(preg, p); + + if (offset == 0) + return 0; + + if (OP(preg, p) == BACK) + return(p-offset); + else + return(p+offset); +} + +#if defined(DEBUG) && !defined(JIM_BOOTSTRAP) + +/* + - regdump - dump a regexp onto stdout in vaguely comprehensible form + */ +static void regdump(regex_t *preg) +{ + int s; + int op = EXACTLY; /* Arbitrary non-END op. */ + int next; + char buf[4]; + + int i; + for (i = 1; i < preg->p; i++) { + printf("%02x ", preg->program[i]); + if (i % 16 == 15) { + printf("\n"); + } + } + printf("\n"); + + s = 1; + while (op != END && s < preg->p) { /* While that wasn't END last time... */ + op = OP(preg, s); + printf("%3d: %s", s, regprop(op)); /* Where, what. */ + next = regnext(preg, s); + if (next == 0) /* Next ptr. */ + printf("(0)"); + else + printf("(%d)", next); + s += 2; + if (op == REP || op == REPMIN || op == REPX || op == REPXMIN) { + int max = preg->program[s]; + int min = preg->program[s + 1]; + if (max == 65535) { + printf("{%d,*}", min); + } + else { + printf("{%d,%d}", min, max); + } + printf(" %d", preg->program[s + 2]); + s += 3; + } + else if (op == ANYOF || op == ANYBUT) { + /* set of ranges */ + + while (preg->program[s]) { + int len = preg->program[s++]; + int first = preg->program[s++]; + buf[utf8_fromunicode(buf, first)] = 0; + printf("%s", buf); + if (len > 1) { + buf[utf8_fromunicode(buf, first + len - 1)] = 0; + printf("-%s", buf); + } + } + s++; + } + else if (op == EXACTLY) { + /* Literal string, where present. */ + + while (preg->program[s]) { + buf[utf8_fromunicode(buf, preg->program[s])] = 0; + printf("%s", buf); + s++; + } + s++; + } + putchar('\n'); + } + + if (op == END) { + /* Header fields of interest. */ + if (preg->regstart) { + buf[utf8_fromunicode(buf, preg->regstart)] = 0; + printf("start '%s' ", buf); + } + if (preg->reganch) + printf("anchored "); + if (preg->regmust != 0) { + int i; + printf("must have:"); + for (i = 0; i < preg->regmlen; i++) { + putchar(preg->program[preg->regmust + i]); + } + putchar('\n'); + } + } + printf("\n"); +} + +/* + - regprop - printable representation of opcode + */ +static const char *regprop( int op ) +{ + static char buf[50]; + + switch (op) { + case BOL: + return "BOL"; + case EOL: + return "EOL"; + case ANY: + return "ANY"; + case ANYOF: + return "ANYOF"; + case ANYBUT: + return "ANYBUT"; + case BRANCH: + return "BRANCH"; + case EXACTLY: + return "EXACTLY"; + case NOTHING: + return "NOTHING"; + case BACK: + return "BACK"; + case END: + return "END"; + case REP: + return "REP"; + case REPMIN: + return "REPMIN"; + case REPX: + return "REPX"; + case REPXMIN: + return "REPXMIN"; + case WORDA: + return "WORDA"; + case WORDZ: + return "WORDZ"; + default: + if (op >= OPEN && op < CLOSE) { + snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN); + } + else if (op >= CLOSE && op < CLOSE_END) { + snprintf(buf, sizeof(buf), "CLOSE%d", op-CLOSE); + } + else { + snprintf(buf, sizeof(buf), "?%d?\n", op); + } + return(buf); + } +} +#endif /* JIM_BOOTSTRAP */ + +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) +{ + static const char *error_strings[] = { + "success", + "no match", + "bad pattern", + "null argument", + "unknown error", + "too big", + "out of memory", + "too many ()", + "parentheses () not balanced", + "braces {} not balanced", + "invalid repetition count(s)", + "extra characters", + "*+ of empty atom", + "nested count", + "internal error", + "count follows nothing", + "trailing backslash", + "corrupted program", + "contains null char", + }; + const char *err; + + if (errcode < 0 || errcode >= REG_ERR_NUM) { + err = "Bad error code"; + } + else { + err = error_strings[errcode]; + } + + return snprintf(errbuf, errbuf_size, "%s", err); +} + +void regfree(regex_t *preg) +{ + free(preg->program); +} + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.h new file mode 100755 index 0000000..79a87e5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimregexp.h @@ -0,0 +1,117 @@ +#ifndef JIMREGEXP_H +#define JIMREGEXP_H + +#ifndef _JIMAUTOCONF_H +#error Need jimautoconf.h +#endif + +#if defined(HAVE_REGCOMP) && !defined(JIM_REGEXP) +/* Use POSIX regex */ +#include <regex.h> + +#else + +#include <stdlib.h> + +/* + * Definitions etc. for regexp(3) routines. + * + * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], + * not the System V one. + * + * 11/04/02 (seiwald) - const-ing for string literals + */ + +typedef struct { + int rm_so; + int rm_eo; +} regmatch_t; + +/* + * The "internal use only" fields in regexp.h are present to pass info from + * compile to execute that permits the execute phase to run lots faster on + * simple cases. They are: + * + * regstart char that must begin a match; '\0' if none obvious + * reganch is the match anchored (at beginning-of-line only)? + * regmust string (pointer into program) that match must include, or NULL + * regmlen length of regmust string + * + * Regstart and reganch permit very fast decisions on suitable starting points + * for a match, cutting down the work a lot. Regmust permits fast rejection + * of lines that cannot possibly match. The regmust tests are costly enough + * that regcomp() supplies a regmust only if the r.e. contains something + * potentially expensive (at present, the only such thing detected is * or + + * at the start of the r.e., which can involve a lot of backup). Regmlen is + * supplied because the test in regexec() needs it and regcomp() is computing + * it anyway. + */ + +typedef struct regexp { + /* -- public -- */ + int re_nsub; /* number of parenthesized subexpressions */ + + /* -- private -- */ + int cflags; /* Flags used when compiling */ + int err; /* Any error which occurred during compile */ + int regstart; /* Internal use only. */ + int reganch; /* Internal use only. */ + int regmust; /* Internal use only. */ + int regmlen; /* Internal use only. */ + int *program; /* Allocated */ + + /* working state - compile */ + const char *regparse; /* Input-scan pointer. */ + int p; /* Current output pos in program */ + int proglen; /* Allocated program size */ + + /* working state - exec */ + int eflags; /* Flags used when executing */ + const char *start; /* Initial string pointer. */ + const char *reginput; /* Current input pointer. */ + const char *regbol; /* Beginning of input, for ^ check. */ + + /* Input to regexec() */ + regmatch_t *pmatch; /* submatches will be stored here */ + int nmatch; /* size of pmatch[] */ +} regexp; + +typedef regexp regex_t; + +#define REG_EXTENDED 0 +#define REG_NEWLINE 1 +#define REG_ICASE 2 + +#define REG_NOTBOL 16 + +enum { + REG_NOERROR, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + REG_BADPAT, /* >= REG_BADPAT is an error */ + REG_ERR_NULL_ARGUMENT, + REG_ERR_UNKNOWN, + REG_ERR_TOO_BIG, + REG_ERR_NOMEM, + REG_ERR_TOO_MANY_PAREN, + REG_ERR_UNMATCHED_PAREN, + REG_ERR_UNMATCHED_BRACES, + REG_ERR_BAD_COUNT, + REG_ERR_JUNK_ON_END, + REG_ERR_OPERAND_COULD_BE_EMPTY, + REG_ERR_NESTED_COUNT, + REG_ERR_INTERNAL, + REG_ERR_COUNT_FOLLOWS_NOTHING, + REG_ERR_TRAILING_BACKSLASH, + REG_ERR_CORRUPTED, + REG_ERR_NULL_CHAR, + REG_ERR_NUM +}; + +int regcomp(regex_t *preg, const char *regex, int cflags); +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); +void regfree(regex_t *preg); + +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimsh.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimsh.c new file mode 100755 index 0000000..2c94468 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/jimsh.c @@ -0,0 +1,111 @@ + +/* Jimsh - An interactive shell for Jim + * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> + * Copyright 2009 Steve Bennett <steveb@workware.net.au> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * A copy of the license is also included in the source distribution + * of Jim, as a TXT file name called LICENSE. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "jim.h" +#include "jimautoconf.h" + +/* From initjimsh.tcl */ +extern int Jim_initjimshInit(Jim_Interp *interp); + +static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) +{ + int n; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + /* Populate argv global var */ + for (n = 0; n < argc; n++) { + Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); + + Jim_ListAppendElement(interp, listObj, obj); + } + + Jim_SetVariableStr(interp, "argv", listObj); + Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); +} + +int main(int argc, char *const argv[]) +{ + int retcode; + Jim_Interp *interp; + + if (argc > 1 && strcmp(argv[1], "--version") == 0) { + printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); + return 0; + } + + /* Create and initialize the interpreter */ + interp = Jim_CreateInterp(); + Jim_RegisterCoreCommands(interp); + + /* Register static extensions */ + if (Jim_InitStaticExtensions(interp) != JIM_OK) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + + Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); + retcode = Jim_initjimshInit(interp); + + if (argc == 1) { + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + if (retcode != JIM_EXIT) { + JimSetArgv(interp, 0, NULL); + retcode = Jim_InteractivePrompt(interp); + } + } + else { + if (argc > 2 && strcmp(argv[1], "-e") == 0) { + JimSetArgv(interp, argc - 3, argv + 3); + retcode = Jim_Eval(interp, argv[2]); + if (retcode != JIM_ERR) { + printf("%s\n", Jim_String(Jim_GetResult(interp))); + } + } + else { + Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); + JimSetArgv(interp, argc - 2, argv + 2); + retcode = Jim_EvalFile(interp, argv[1]); + } + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); + } + } + if (retcode == JIM_EXIT) { + retcode = Jim_GetExitCode(interp); + } + else if (retcode == JIM_ERR) { + retcode = 1; + } + else { + retcode = 0; + } + Jim_FreeInterp(interp); + return retcode; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.c new file mode 100755 index 0000000..4065d06 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.c @@ -0,0 +1,1379 @@ +/* linenoise.c -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * You can find the latest source code at: + * + * http://github.com/antirez/linenoise + * + * Does a number of crazy assumptions that happen to be true in 99.9999% of + * the 2010 UNIX computers around. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ------------------------------------------------------------------------ + * + * References: + * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html + * + * Todo list: + * - Win32 support + * - Save and load history containing newlines + * + * Bloat: + * - Completion? + * + * List of escape sequences used by this program, we do everything just + * a few sequences. In order to be so cheap we may have some + * flickering effect with some slow terminal, but the lesser sequences + * the more compatible. + * + * CHA (Cursor Horizontal Absolute) + * Sequence: ESC [ n G + * Effect: moves cursor to column n (1 based) + * + * EL (Erase Line) + * Sequence: ESC [ n K + * Effect: if n is 0 or missing, clear from cursor to end of line + * Effect: if n is 1, clear from beginning of line to cursor + * Effect: if n is 2, clear entire line + * + * CUF (CUrsor Forward) + * Sequence: ESC [ n C + * Effect: moves cursor forward of n chars + * + * The following are used to clear the screen: ESC [ H ESC [ 2 J + * This is actually composed of two sequences: + * + * cursorhome + * Sequence: ESC [ H + * Effect: moves the cursor to upper left corner + * + * ED2 (Clear entire screen) + * Sequence: ESC [ 2 J + * Effect: clear the whole screen + * + * == For highlighting control characters, we also use the following two == + * SO (enter StandOut) + * Sequence: ESC [ 7 m + * Effect: Uses some standout mode such as reverse video + * + * SE (Standout End) + * Sequence: ESC [ 0 m + * Effect: Exit standout mode + * + * == Only used if TIOCGWINSZ fails == + * DSR/CPR (Report cursor position) + * Sequence: ESC [ 6 n + * Effect: reports current cursor position as ESC [ NNN ; MMM R + */ + +#ifdef __MINGW32__ +#include <windows.h> +#include <fcntl.h> +#define USE_WINCONSOLE +#else +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/poll.h> +#define USE_TERMIOS +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +#include "linenoise.h" + +#include "jim-config.h" +#ifdef JIM_UTF8 +#define USE_UTF8 +#endif +#include "utf8.h" + +#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100 +#define LINENOISE_MAX_LINE 4096 + +#define ctrl(C) ((C) - '@') + +/* Use -ve numbers here to co-exist with normal unicode chars */ +enum { + SPECIAL_NONE, + SPECIAL_UP = -20, + SPECIAL_DOWN = -21, + SPECIAL_LEFT = -22, + SPECIAL_RIGHT = -23, + SPECIAL_DELETE = -24, + SPECIAL_HOME = -25, + SPECIAL_END = -26, +}; + +static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN; +static int history_len = 0; +static char **history = NULL; + +/* Structure to contain the status of the current (being edited) line */ +struct current { + char *buf; /* Current buffer. Always null terminated */ + int bufmax; /* Size of the buffer, including space for the null termination */ + int len; /* Number of bytes in 'buf' */ + int chars; /* Number of chars in 'buf' (utf-8 chars) */ + int pos; /* Cursor position, measured in chars */ + int cols; /* Size of the window, in chars */ + const char *prompt; +#if defined(USE_TERMIOS) + int fd; /* Terminal fd */ +#elif defined(USE_WINCONSOLE) + HANDLE outh; /* Console output handle */ + HANDLE inh; /* Console input handle */ + int rows; /* Screen rows */ + int x; /* Current column during output */ + int y; /* Current row */ +#endif +}; + +static int fd_read(struct current *current); +static int getWindowSize(struct current *current); + +void linenoiseHistoryFree(void) { + if (history) { + int j; + + for (j = 0; j < history_len; j++) + free(history[j]); + free(history); + history = NULL; + } +} + +#if defined(USE_TERMIOS) +static void linenoiseAtExit(void); +static struct termios orig_termios; /* in order to restore at exit */ +static int rawmode = 0; /* for atexit() function to check if restore is needed*/ +static int atexit_registered = 0; /* register atexit just 1 time */ + +static const char *unsupported_term[] = {"dumb","cons25",NULL}; + +static int isUnsupportedTerm(void) { + char *term = getenv("TERM"); + + if (term) { + int j; + for (j = 0; unsupported_term[j]; j++) { + if (strcasecmp(term, unsupported_term[j]) == 0) { + return 1; + } + } + } + return 0; +} + +static int enableRawMode(struct current *current) { + struct termios raw; + + current->fd = STDIN_FILENO; + + if (!isatty(current->fd) || isUnsupportedTerm() || + tcgetattr(current->fd, &orig_termios) == -1) { +fatal: + errno = ENOTTY; + return -1; + } + + if (!atexit_registered) { + atexit(linenoiseAtExit); + atexit_registered = 1; + } + + raw = orig_termios; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + /* output modes - disable post processing */ + raw.c_oflag &= ~(OPOST); + /* control modes - set 8 bit chars */ + raw.c_cflag |= (CS8); + /* local modes - choing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr(current->fd,TCSADRAIN,&raw) < 0) { + goto fatal; + } + rawmode = 1; + + current->cols = 0; + return 0; +} + +static void disableRawMode(struct current *current) { + /* Don't even check the return value as it's too late. */ + if (rawmode && tcsetattr(current->fd,TCSADRAIN,&orig_termios) != -1) + rawmode = 0; +} + +/* At exit we'll try to fix the terminal to the initial conditions. */ +static void linenoiseAtExit(void) { + if (rawmode) { + tcsetattr(STDIN_FILENO, TCSADRAIN, &orig_termios); + } + linenoiseHistoryFree(); +} + +/* gcc/glibc insists that we care about the return code of write! */ +#define IGNORE_RC(EXPR) if (EXPR) {} + +/* This is fdprintf() on some systems, but use a different + * name to avoid conflicts + */ +static void fd_printf(int fd, const char *format, ...) +{ + va_list args; + char buf[64]; + int n; + + va_start(args, format); + n = vsnprintf(buf, sizeof(buf), format, args); + va_end(args); + IGNORE_RC(write(fd, buf, n)); +} + +static void clearScreen(struct current *current) +{ + fd_printf(current->fd, "\x1b[H\x1b[2J"); +} + +static void cursorToLeft(struct current *current) +{ + fd_printf(current->fd, "\x1b[1G"); +} + +static int outputChars(struct current *current, const char *buf, int len) +{ + return write(current->fd, buf, len); +} + +static void outputControlChar(struct current *current, char ch) +{ + fd_printf(current->fd, "\033[7m^%c\033[0m", ch); +} + +static void eraseEol(struct current *current) +{ + fd_printf(current->fd, "\x1b[0K"); +} + +static void setCursorPos(struct current *current, int x) +{ + fd_printf(current->fd, "\x1b[1G\x1b[%dC", x); +} + +/** + * Reads a char from 'fd', waiting at most 'timeout' milliseconds. + * + * A timeout of -1 means to wait forever. + * + * Returns -1 if no char is received within the time or an error occurs. + */ +static int fd_read_char(int fd, int timeout) +{ + struct pollfd p; + unsigned char c; + + p.fd = fd; + p.events = POLLIN; + + if (poll(&p, 1, timeout) == 0) { + /* timeout */ + return -1; + } + if (read(fd, &c, 1) != 1) { + return -1; + } + return c; +} + +/** + * Reads a complete utf-8 character + * and returns the unicode value, or -1 on error. + */ +static int fd_read(struct current *current) +{ +#ifdef USE_UTF8 + char buf[4]; + int n; + int i; + int c; + + if (read(current->fd, &buf[0], 1) != 1) { + return -1; + } + n = utf8_charlen(buf[0]); + if (n < 1 || n > 3) { + return -1; + } + for (i = 1; i < n; i++) { + if (read(current->fd, &buf[i], 1) != 1) { + return -1; + } + } + buf[n] = 0; + /* decode and return the character */ + utf8_tounicode(buf, &c); + return c; +#else + return fd_read_char(current->fd, -1); +#endif +} + +static int getWindowSize(struct current *current) +{ + struct winsize ws; + + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0 && ws.ws_col != 0) { + current->cols = ws.ws_col; + return 0; + } + + /* Failed to query the window size. Perhaps we are on a serial terminal. + * Try to query the width by sending the cursor as far to the right + * and reading back the cursor position. + * Note that this is only done once per call to linenoise rather than + * every time the line is refreshed for efficiency reasons. + */ + if (current->cols == 0) { + current->cols = 80; + + /* Move cursor far right and report cursor position */ + fd_printf(current->fd, "\x1b[999G" "\x1b[6n"); + + /* Parse the response: ESC [ rows ; cols R */ + if (fd_read_char(current->fd, 100) == 0x1b && fd_read_char(current->fd, 100) == '[') { + int n = 0; + while (1) { + int ch = fd_read_char(current->fd, 100); + if (ch == ';') { + /* Ignore rows */ + n = 0; + } + else if (ch == 'R') { + /* Got cols */ + if (n != 0 && n < 1000) { + current->cols = n; + } + break; + } + else if (ch >= 0 && ch <= '9') { + n = n * 10 + ch - '0'; + } + else { + break; + } + } + } + } + return 0; +} + +/** + * If escape (27) was received, reads subsequent + * chars to determine if this is a known special key. + * + * Returns SPECIAL_NONE if unrecognised, or -1 if EOF. + * + * If no additional char is received within a short time, + * 27 is returned. + */ +static int check_special(int fd) +{ + int c = fd_read_char(fd, 50); + int c2; + + if (c < 0) { + return 27; + } + + c2 = fd_read_char(fd, 50); + if (c2 < 0) { + return c2; + } + if (c == '[' || c == 'O') { + /* Potential arrow key */ + switch (c2) { + case 'A': + return SPECIAL_UP; + case 'B': + return SPECIAL_DOWN; + case 'C': + return SPECIAL_RIGHT; + case 'D': + return SPECIAL_LEFT; + case 'F': + return SPECIAL_END; + case 'H': + return SPECIAL_HOME; + } + } + if (c == '[' && c2 >= '1' && c2 <= '6') { + /* extended escape */ + int c3 = fd_read_char(fd, 50); + if (c2 == '3' && c3 == '~') { + /* delete char under cursor */ + return SPECIAL_DELETE; + } + while (c3 != -1 && c3 != '~') { + /* .e.g \e[12~ or '\e[11;2~ discard the complete sequence */ + c3 = fd_read_char(fd, 50); + } + } + + return SPECIAL_NONE; +} +#elif defined(USE_WINCONSOLE) + +static DWORD orig_consolemode = 0; + +static int enableRawMode(struct current *current) { + DWORD n; + INPUT_RECORD irec; + + current->outh = GetStdHandle(STD_OUTPUT_HANDLE); + current->inh = GetStdHandle(STD_INPUT_HANDLE); + + if (!PeekConsoleInput(current->inh, &irec, 1, &n)) { + return -1; + } + if (getWindowSize(current) != 0) { + return -1; + } + if (GetConsoleMode(current->inh, &orig_consolemode)) { + SetConsoleMode(current->inh, ENABLE_PROCESSED_INPUT); + } + return 0; +} + +static void disableRawMode(struct current *current) +{ + SetConsoleMode(current->inh, orig_consolemode); +} + +static void clearScreen(struct current *current) +{ + COORD topleft = { 0, 0 }; + DWORD n; + + FillConsoleOutputCharacter(current->outh, ' ', + current->cols * current->rows, topleft, &n); + FillConsoleOutputAttribute(current->outh, + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, + current->cols * current->rows, topleft, &n); + SetConsoleCursorPosition(current->outh, topleft); +} + +static void cursorToLeft(struct current *current) +{ + COORD pos = { 0, current->y }; + DWORD n; + + FillConsoleOutputAttribute(current->outh, + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN, current->cols, pos, &n); + current->x = 0; +} + +static int outputChars(struct current *current, const char *buf, int len) +{ + COORD pos = { current->x, current->y }; + WriteConsoleOutputCharacter(current->outh, buf, len, pos, 0); + current->x += len; + return 0; +} + +static void outputControlChar(struct current *current, char ch) +{ + COORD pos = { current->x, current->y }; + DWORD n; + + FillConsoleOutputAttribute(current->outh, BACKGROUND_INTENSITY, 2, pos, &n); + outputChars(current, "^", 1); + outputChars(current, &ch, 1); +} + +static void eraseEol(struct current *current) +{ + COORD pos = { current->x, current->y }; + DWORD n; + + FillConsoleOutputCharacter(current->outh, ' ', current->cols - current->x, pos, &n); +} + +static void setCursorPos(struct current *current, int x) +{ + COORD pos = { x, current->y }; + + SetConsoleCursorPosition(current->outh, pos); + current->x = x; +} + +static int fd_read(struct current *current) +{ + while (1) { + INPUT_RECORD irec; + DWORD n; + if (WaitForSingleObject(current->inh, INFINITE) != WAIT_OBJECT_0) { + break; + } + if (!ReadConsoleInput (current->inh, &irec, 1, &n)) { + break; + } + if (irec.EventType == KEY_EVENT && irec.Event.KeyEvent.bKeyDown) { + KEY_EVENT_RECORD *k = &irec.Event.KeyEvent; + if (k->dwControlKeyState & ENHANCED_KEY) { + switch (k->wVirtualKeyCode) { + case VK_LEFT: + return SPECIAL_LEFT; + case VK_RIGHT: + return SPECIAL_RIGHT; + case VK_UP: + return SPECIAL_UP; + case VK_DOWN: + return SPECIAL_DOWN; + case VK_DELETE: + return SPECIAL_DELETE; + case VK_HOME: + return SPECIAL_HOME; + case VK_END: + return SPECIAL_END; + } + } + /* Note that control characters are already translated in AsciiChar */ + else { +#ifdef USE_UTF8 + return k->uChar.UnicodeChar; +#else + return k->uChar.AsciiChar; +#endif + } + } + } + return -1; +} + +static int getWindowSize(struct current *current) +{ + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(current->outh, &info)) { + return -1; + } + current->cols = info.dwSize.X; + current->rows = info.dwSize.Y; + if (current->cols <= 0 || current->rows <= 0) { + current->cols = 80; + return -1; + } + current->y = info.dwCursorPosition.Y; + current->x = info.dwCursorPosition.X; + return 0; +} +#endif + +static int utf8_getchars(char *buf, int c) +{ +#ifdef USE_UTF8 + return utf8_fromunicode(buf, c); +#else + *buf = c; + return 1; +#endif +} + +/** + * Returns the unicode character at the given offset, + * or -1 if none. + */ +static int get_char(struct current *current, int pos) +{ + if (pos >= 0 && pos < current->chars) { + int c; + int i = utf8_index(current->buf, pos); + (void)utf8_tounicode(current->buf + i, &c); + return c; + } + return -1; +} + +static void refreshLine(const char *prompt, struct current *current) +{ + int plen; + int pchars; + int backup = 0; + int i; + const char *buf = current->buf; + int chars = current->chars; + int pos = current->pos; + int b; + int ch; + int n; + + /* Should intercept SIGWINCH. For now, just get the size every time */ + getWindowSize(current); + + plen = strlen(prompt); + pchars = utf8_strlen(prompt, plen); + + /* Account for a line which is too long to fit in the window. + * Note that control chars require an extra column + */ + + /* How many cols are required to the left of 'pos'? + * The prompt, plus one extra for each control char + */ + n = pchars + utf8_strlen(buf, current->len); + b = 0; + for (i = 0; i < pos; i++) { + b += utf8_tounicode(buf + b, &ch); + if (ch < ' ') { + n++; + } + } + + /* If too many are need, strip chars off the front of 'buf' + * until it fits. Note that if the current char is a control character, + * we need one extra col. + */ + if (current->pos < current->chars && get_char(current, current->pos) < ' ') { + n++; + } + + while (n >= current->cols) { + b = utf8_tounicode(buf, &ch); + if (ch < ' ') { + n--; + } + n--; + buf += b; + pos--; + chars--; + } + + /* Cursor to left edge, then the prompt */ + cursorToLeft(current); + outputChars(current, prompt, plen); + + /* Now the current buffer content */ + + /* Need special handling for control characters. + * If we hit 'cols', stop. + */ + b = 0; /* unwritted bytes */ + n = 0; /* How many control chars were written */ + for (i = 0; i < chars; i++) { + int ch; + int w = utf8_tounicode(buf + b, &ch); + if (ch < ' ') { + n++; + } + if (pchars + i + n >= current->cols) { + break; + } + if (ch < ' ') { + /* A control character, so write the buffer so far */ + outputChars(current, buf, b); + buf += b + w; + b = 0; + outputControlChar(current, ch + '@'); + if (i < pos) { + backup++; + } + } + else { + b += w; + } + } + outputChars(current, buf, b); + + /* Erase to right, move cursor to original position */ + eraseEol(current); + setCursorPos(current, pos + pchars + backup); +} + +static void set_current(struct current *current, const char *str) +{ + strncpy(current->buf, str, current->bufmax); + current->buf[current->bufmax - 1] = 0; + current->len = strlen(current->buf); + current->pos = current->chars = utf8_strlen(current->buf, current->len); +} + +static int has_room(struct current *current, int bytes) +{ + return current->len + bytes < current->bufmax - 1; +} + +/** + * Removes the char at 'pos'. + * + * Returns 1 if the line needs to be refreshed, 2 if not + * and 0 if nothing was removed + */ +static int remove_char(struct current *current, int pos) +{ + if (pos >= 0 && pos < current->chars) { + int p1, p2; + int ret = 1; + p1 = utf8_index(current->buf, pos); + p2 = p1 + utf8_index(current->buf + p1, 1); + +#ifdef USE_TERMIOS + /* optimise remove char in the case of removing the last char */ + if (current->pos == pos + 1 && current->pos == current->chars) { + if (current->buf[pos] >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { + ret = 2; + fd_printf(current->fd, "\b \b"); + } + } +#endif + + /* Move the null char too */ + memmove(current->buf + p1, current->buf + p2, current->len - p2 + 1); + current->len -= (p2 - p1); + current->chars--; + + if (current->pos > pos) { + current->pos--; + } + return ret; + } + return 0; +} + +/** + * Insert 'ch' at position 'pos' + * + * Returns 1 if the line needs to be refreshed, 2 if not + * and 0 if nothing was inserted (no room) + */ +static int insert_char(struct current *current, int pos, int ch) +{ + char buf[3]; + int n = utf8_getchars(buf, ch); + + if (has_room(current, n) && pos >= 0 && pos <= current->chars) { + int p1, p2; + int ret = 1; + p1 = utf8_index(current->buf, pos); + p2 = p1 + n; + +#ifdef USE_TERMIOS + /* optimise the case where adding a single char to the end and no scrolling is needed */ + if (current->pos == pos && current->chars == pos) { + if (ch >= ' ' && utf8_strlen(current->prompt, -1) + utf8_strlen(current->buf, current->len) < current->cols - 1) { + IGNORE_RC(write(current->fd, buf, n)); + ret = 2; + } + } +#endif + + memmove(current->buf + p2, current->buf + p1, current->len - p1); + memcpy(current->buf + p1, buf, n); + current->len += n; + + current->chars++; + if (current->pos >= pos) { + current->pos++; + } + return ret; + } + return 0; +} + +/** + * Returns 0 if no chars were removed or non-zero otherwise. + */ +static int remove_chars(struct current *current, int pos, int n) +{ + int removed = 0; + while (n-- && remove_char(current, pos)) { + removed++; + } + return removed; +} + +#ifndef NO_COMPLETION +static linenoiseCompletionCallback *completionCallback = NULL; + +static void beep() { +#ifdef USE_TERMIOS + fprintf(stderr, "\x7"); + fflush(stderr); +#endif +} + +static void freeCompletions(linenoiseCompletions *lc) { + size_t i; + for (i = 0; i < lc->len; i++) + free(lc->cvec[i]); + free(lc->cvec); +} + +static int completeLine(struct current *current) { + linenoiseCompletions lc = { 0, NULL }; + int c = 0; + + completionCallback(current->buf,&lc); + if (lc.len == 0) { + beep(); + } else { + size_t stop = 0, i = 0; + + while(!stop) { + /* Show completion or original buffer */ + if (i < lc.len) { + struct current tmp = *current; + tmp.buf = lc.cvec[i]; + tmp.pos = tmp.len = strlen(tmp.buf); + tmp.chars = utf8_strlen(tmp.buf, tmp.len); + refreshLine(current->prompt, &tmp); + } else { + refreshLine(current->prompt, current); + } + + c = fd_read(current); + if (c == -1) { + break; + } + + switch(c) { + case '\t': /* tab */ + i = (i+1) % (lc.len+1); + if (i == lc.len) beep(); + break; + case 27: /* escape */ + /* Re-show original buffer */ + if (i < lc.len) { + refreshLine(current->prompt, current); + } + stop = 1; + break; + default: + /* Update buffer and return */ + if (i < lc.len) { + set_current(current,lc.cvec[i]); + } + stop = 1; + break; + } + } + } + + freeCompletions(&lc); + return c; /* Return last read character */ +} + +/* Register a callback function to be called for tab-completion. */ +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { + completionCallback = fn; +} + +void linenoiseAddCompletion(linenoiseCompletions *lc, const char *str) { + lc->cvec = (char **)realloc(lc->cvec,sizeof(char*)*(lc->len+1)); + lc->cvec[lc->len++] = strdup(str); +} + +#endif + +static int linenoisePrompt(struct current *current) { + int history_index = 0; + + /* The latest history entry is always our current buffer, that + * initially is just an empty string. */ + linenoiseHistoryAdd(""); + + set_current(current, ""); + refreshLine(current->prompt, current); + + while(1) { + int dir = -1; + int c = fd_read(current); + +#ifndef NO_COMPLETION + /* Only autocomplete when the callback is set. It returns < 0 when + * there was an error reading from fd. Otherwise it will return the + * character that should be handled next. */ + if (c == 9 && completionCallback != NULL) { + c = completeLine(current); + /* Return on errors */ + if (c < 0) return current->len; + /* Read next character when 0 */ + if (c == 0) continue; + } +#endif + +process_char: + if (c == -1) return current->len; +#ifdef USE_TERMIOS + if (c == 27) { /* escape sequence */ + c = check_special(current->fd); + } +#endif + switch(c) { + case '\r': /* enter */ + history_len--; + free(history[history_len]); + return current->len; + case ctrl('C'): /* ctrl-c */ + errno = EAGAIN; + return -1; + case 127: /* backspace */ + case ctrl('H'): + if (remove_char(current, current->pos - 1) == 1) { + refreshLine(current->prompt, current); + } + break; + case ctrl('D'): /* ctrl-d */ + if (current->len == 0) { + /* Empty line, so EOF */ + history_len--; + free(history[history_len]); + return -1; + } + /* Otherwise delete char to right of cursor */ + if (remove_char(current, current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('W'): /* ctrl-w */ + /* eat any spaces on the left */ + { + int pos = current->pos; + while (pos > 0 && get_char(current, pos - 1) == ' ') { + pos--; + } + + /* now eat any non-spaces on the left */ + while (pos > 0 && get_char(current, pos - 1) != ' ') { + pos--; + } + + if (remove_chars(current, pos, current->pos - pos)) { + refreshLine(current->prompt, current); + } + } + break; + case ctrl('R'): /* ctrl-r */ + { + /* Display the reverse-i-search prompt and process chars */ + char rbuf[50]; + char rprompt[80]; + int rchars = 0; + int rlen = 0; + int searchpos = history_len - 1; + + rbuf[0] = 0; + while (1) { + int n = 0; + const char *p = NULL; + int skipsame = 0; + int searchdir = -1; + + snprintf(rprompt, sizeof(rprompt), "(reverse-i-search)'%s': ", rbuf); + refreshLine(rprompt, current); + c = fd_read(current); + if (c == ctrl('H') || c == 127) { + if (rchars) { + int p = utf8_index(rbuf, --rchars); + rbuf[p] = 0; + rlen = strlen(rbuf); + } + continue; + } +#ifdef USE_TERMIOS + if (c == 27) { + c = check_special(current->fd); + } +#endif + if (c == ctrl('P') || c == SPECIAL_UP) { + /* Search for the previous (earlier) match */ + if (searchpos > 0) { + searchpos--; + } + skipsame = 1; + } + else if (c == ctrl('N') || c == SPECIAL_DOWN) { + /* Search for the next (later) match */ + if (searchpos < history_len) { + searchpos++; + } + searchdir = 1; + skipsame = 1; + } + else if (c >= ' ') { + if (rlen >= (int)sizeof(rbuf) + 3) { + continue; + } + + n = utf8_getchars(rbuf + rlen, c); + rlen += n; + rchars++; + rbuf[rlen] = 0; + + /* Adding a new char resets the search location */ + searchpos = history_len - 1; + } + else { + /* Exit from incremental search mode */ + break; + } + + /* Now search through the history for a match */ + for (; searchpos >= 0 && searchpos < history_len; searchpos += searchdir) { + p = strstr(history[searchpos], rbuf); + if (p) { + /* Found a match */ + if (skipsame && strcmp(history[searchpos], current->buf) == 0) { + /* But it is identical, so skip it */ + continue; + } + /* Copy the matching line and set the cursor position */ + set_current(current,history[searchpos]); + current->pos = utf8_strlen(history[searchpos], p - history[searchpos]); + break; + } + } + if (!p && n) { + /* No match, so don't add it */ + rchars--; + rlen -= n; + rbuf[rlen] = 0; + } + } + if (c == ctrl('G') || c == ctrl('C')) { + /* ctrl-g terminates the search with no effect */ + set_current(current, ""); + c = 0; + } + else if (c == ctrl('J')) { + /* ctrl-j terminates the search leaving the buffer in place */ + c = 0; + } + /* Go process the char normally */ + refreshLine(current->prompt, current); + goto process_char; + } + break; + case ctrl('T'): /* ctrl-t */ + if (current->pos > 0 && current->pos < current->chars) { + c = get_char(current, current->pos); + remove_char(current, current->pos); + insert_char(current, current->pos - 1, c); + refreshLine(current->prompt, current); + } + break; + case ctrl('V'): /* ctrl-v */ + if (has_room(current, 3)) { + /* Insert the ^V first */ + if (insert_char(current, current->pos, c)) { + refreshLine(current->prompt, current); + /* Now wait for the next char. Can insert anything except \0 */ + c = fd_read(current); + + /* Remove the ^V first */ + remove_char(current, current->pos - 1); + if (c != -1) { + /* Insert the actual char */ + insert_char(current, current->pos, c); + } + refreshLine(current->prompt, current); + } + } + break; + case ctrl('B'): + case SPECIAL_LEFT: + if (current->pos > 0) { + current->pos--; + refreshLine(current->prompt, current); + } + break; + case ctrl('F'): + case SPECIAL_RIGHT: + if (current->pos < current->chars) { + current->pos++; + refreshLine(current->prompt, current); + } + break; + case ctrl('P'): + case SPECIAL_UP: + dir = 1; + case ctrl('N'): + case SPECIAL_DOWN: + if (history_len > 1) { + /* Update the current history entry before to + * overwrite it with tne next one. */ + free(history[history_len-1-history_index]); + history[history_len-1-history_index] = strdup(current->buf); + /* Show the new entry */ + history_index += dir; + if (history_index < 0) { + history_index = 0; + break; + } else if (history_index >= history_len) { + history_index = history_len-1; + break; + } + set_current(current, history[history_len-1-history_index]); + refreshLine(current->prompt, current); + } + break; + + case SPECIAL_DELETE: + if (remove_char(current, current->pos) == 1) { + refreshLine(current->prompt, current); + } + break; + case SPECIAL_HOME: + current->pos = 0; + refreshLine(current->prompt, current); + break; + case SPECIAL_END: + current->pos = current->chars; + refreshLine(current->prompt, current); + break; + default: + /* Only tab is allowed without ^V */ + if (c == '\t' || c >= ' ') { + if (insert_char(current, current->pos, c) == 1) { + refreshLine(current->prompt, current); + } + } + break; + case ctrl('U'): /* Ctrl+u, delete to beginning of line. */ + if (remove_chars(current, 0, current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('K'): /* Ctrl+k, delete from current to end of line. */ + if (remove_chars(current, current->pos, current->chars - current->pos)) { + refreshLine(current->prompt, current); + } + break; + case ctrl('A'): /* Ctrl+a, go to the start of the line */ + current->pos = 0; + refreshLine(current->prompt, current); + break; + case ctrl('E'): /* ctrl+e, go to the end of the line */ + current->pos = current->chars; + refreshLine(current->prompt, current); + break; + case ctrl('L'): /* Ctrl+L, clear screen */ + /* clear screen */ + clearScreen(current); + /* Force recalc of window size for serial terminals */ + current->cols = 0; + refreshLine(current->prompt, current); + break; + } + } + return current->len; +} + +char *linenoise(const char *prompt) +{ + int count; + struct current current; + char buf[LINENOISE_MAX_LINE]; + + if (enableRawMode(¤t) == -1) { + printf("%s", prompt); + fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + return NULL; + } + count = strlen(buf); + if (count && buf[count-1] == '\n') { + count--; + buf[count] = '\0'; + } + } + else + { + current.buf = buf; + current.bufmax = sizeof(buf); + current.len = 0; + current.chars = 0; + current.pos = 0; + current.prompt = prompt; + + count = linenoisePrompt(¤t); + disableRawMode(¤t); + printf("\n"); + if (count == -1) { + return NULL; + } + } + return strdup(buf); +} + +/* Using a circular buffer is smarter, but a bit more complex to handle. */ +int linenoiseHistoryAdd(const char *line) { + char *linecopy; + + if (history_max_len == 0) return 0; + if (history == NULL) { + history = (char**)malloc(sizeof(char*)*history_max_len); + if (history == NULL) return 0; + memset(history,0,(sizeof(char*)*history_max_len)); + } + linecopy = strdup(line); + if (!linecopy) return 0; + if (history_len == history_max_len) { + free(history[0]); + memmove(history,history+1,sizeof(char*)*(history_max_len-1)); + history_len--; + } + history[history_len] = linecopy; + history_len++; + return 1; +} + +int linenoiseHistorySetMaxLen(int len) { + char **newHistory; + + if (len < 1) return 0; + if (history) { + int tocopy = history_len; + + newHistory = (char**)malloc(sizeof(char*)*len); + if (newHistory == NULL) return 0; + if (len < tocopy) tocopy = len; + memcpy(newHistory,history+(history_max_len-tocopy), sizeof(char*)*tocopy); + free(history); + history = newHistory; + } + history_max_len = len; + if (history_len > history_max_len) + history_len = history_max_len; + return 1; +} + +/* Save the history in the specified file. On success 0 is returned + * otherwise -1 is returned. */ +int linenoiseHistorySave(const char *filename) { + FILE *fp = fopen(filename,"w"); + int j; + + if (fp == NULL) return -1; + for (j = 0; j < history_len; j++) { + const char *str = history[j]; + /* Need to encode backslash, nl and cr */ + while (*str) { + if (*str == '\\') { + fputs("\\\\", fp); + } + else if (*str == '\n') { + fputs("\\n", fp); + } + else if (*str == '\r') { + fputs("\\r", fp); + } + else { + fputc(*str, fp); + } + str++; + } + fputc('\n', fp); + } + + fclose(fp); + return 0; +} + +/* Load the history from the specified file. If the file does not exist + * zero is returned and no operation is performed. + * + * If the file exists and the operation succeeded 0 is returned, otherwise + * on error -1 is returned. */ +int linenoiseHistoryLoad(const char *filename) { + FILE *fp = fopen(filename,"r"); + char buf[LINENOISE_MAX_LINE]; + + if (fp == NULL) return -1; + + while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { + char *src, *dest; + + /* Decode backslash escaped values */ + for (src = dest = buf; *src; src++) { + char ch = *src; + + if (ch == '\\') { + src++; + if (*src == 'n') { + ch = '\n'; + } + else if (*src == 'r') { + ch = '\r'; + } else { + ch = *src; + } + } + *dest++ = ch; + } + /* Remove trailing newline */ + if (dest != buf && (dest[-1] == '\n' || dest[-1] == '\r')) { + dest--; + } + *dest = 0; + + linenoiseHistoryAdd(buf); + } + fclose(fp); + return 0; +} + +/* Provide access to the history buffer. + * + * If 'len' is not NULL, the length is stored in *len. + */ +char **linenoiseHistory(int *len) { + if (len) { + *len = history_len; + } + return history; +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.h new file mode 100755 index 0000000..dcf22f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/linenoise.h @@ -0,0 +1,62 @@ +/* linenoise.h -- guerrilla line editing library against the idea that a + * line editing lib needs to be 20,000 lines of C code. + * + * See linenoise.c for more information. + * + * ------------------------------------------------------------------------ + * + * Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LINENOISE_H +#define __LINENOISE_H + +/* Currently never enable completion */ +#define NO_COMPLETION + +#ifndef NO_COMPLETION +typedef struct linenoiseCompletions { + size_t len; + char **cvec; +} linenoiseCompletions; + +typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); +void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); +void linenoiseAddCompletion(linenoiseCompletions *, const char *); +#endif + +char *linenoise(const char *prompt); +int linenoiseHistoryAdd(const char *line); +int linenoiseHistorySetMaxLen(int len); +int linenoiseHistorySave(const char *filename); +int linenoiseHistoryLoad(const char *filename); +void linenoiseHistoryFree(void); +char **linenoiseHistory(int *len); + +#endif /* __LINENOISE_H */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim new file mode 100755 index 0000000..cc2cd5d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-bootstrap-jim @@ -0,0 +1,104 @@ +#!/bin/sh + +# This script writes to stdout, a single source file (e.g. jimsh0.c) +# which can be compiled to provide a bootstrap version of jimsh. +# e.g. cc -o jimsh0 jimsh0.c + +makeext() +{ + source="$1" + basename=`basename "$source" .tcl` +cat <<EOF +int Jim_${basename}Init(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "$basename", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "$source", 1, +EOF + +# Note: Keep newlines so that line numbers match in error messages +sed -e 's/^[ ]*#.*//' -e 's@\\@\\\\@g' -e 's@"@\\"@g' -e 's@^\(.*\)$@"\1\\n"@' $source + +echo ");" +echo "}" +} + +makeloadexts() +{ +cat <<EOF +int Jim_InitStaticExtensions(Jim_Interp *interp) +EOF + echo "{" + for ext in $*; do + echo "extern int Jim_${ext}Init(Jim_Interp *);" + done + for ext in $*; do + echo "Jim_${ext}Init(interp);" + done + echo "return JIM_OK;" + echo "}" +} + +cexts="aio readdir regexp file exec clock array" +tclexts="bootstrap initjimsh glob stdlib tclcompat" + +# Note ordering +allexts="bootstrap aio readdir glob regexp file exec clock array stdlib tclcompat" + +echo "/* This is single source file, bootstrap version of Jim Tcl. See http://jim.berlios.de/ */" + +# define some core features +for i in _GNU_SOURCE JIM_TCL_COMPAT JIM_REFERENCES JIM_ANSIC JIM_REGEXP HAVE_NO_AUTOCONF _JIMAUTOCONF_H; do + echo "#define $i" +done +echo '#define TCL_LIBRARY "."' +# and extensions +for i in $allexts; do + echo "#define jim_ext_$i" +done + +# Can we make a bootstrap jimsh work even on mingw32? +cat <<EOF +#if defined(__MINGW32__) +#define TCL_PLATFORM_OS "mingw" +#define TCL_PLATFORM_PLATFORM "windows" +#define TCL_PLATFORM_PATH_SEPARATOR ";" +#define HAVE_MKDIR_ONE_ARG +#define HAVE_SYSTEM +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#else +#define TCL_PLATFORM_OS "unknown" +#define TCL_PLATFORM_PLATFORM "unix" +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#define HAVE_VFORK +#define HAVE_WAITPID +#endif +EOF + +outputsource() +{ + sed -e '/#include.*jim/d' -e '/#include.*utf8/d' \ + -e '/^#.*if.*JIM_BOOTSTRAP/,/^#endif.*JIM_BOOTSTRAP/d' \ + -e 's/\/\*.*\*\///' -e '/^[ ]*\/\*/,/\*\//d' $1 +} + +# Now output header files, removing references to jim header files +for i in utf8.h jim.h jim-subcmd.h jimregexp.h ; do + outputsource $i +done + +# Now extension source code +for i in $tclexts; do + makeext $i.tcl +done +for i in $cexts; do + outputsource jim-$i.c +done +makeloadexts $allexts + +# And finally the core source code +for i in jim.c jim-subcmd.c utf8.c jim-interactive.c jim-format.c jimregexp.c jimsh.c; do + outputsource $i +done diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl new file mode 100755 index 0000000..fd1a056 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-c-ext.tcl @@ -0,0 +1,38 @@ +#!/usr/bin/env tclsh + +# Usage: make-c-ext.tcl source.tcl >jim-source.c + +# Converts a Tcl source file into C source suitable +# for loading as a static extension. + +lassign $argv source + +if {![string match *.tcl $source]} { + error "Source $source is not a .tcl file" +} + +# Read the Tcl source and convert to C +# Note that no lines are removed in order to preserve line numbering +set sourcelines {} +set f [open $source] +while {[gets $f buf] >= 0} { + # Remove comment lines + regsub {^[ \t]*#.*$} $buf "" buf + # Escape quotes and backlashes + set buf [string map [list \\ \\\\ \" \\"] $buf] + lappend sourcelines \"$buf\\n\" +} +close $f + +lappend lines {/* autogenerated - do not edit */} +lappend lines {#include <jim.h>} +set basename [file tail $source] +set pkgname [file rootname $basename] + +lappend lines "int Jim_${pkgname}Init(Jim_Interp *interp)" +lappend lines "\{" +lappend lines "\tif (Jim_PackageProvide(interp, \"$pkgname\", \"1.0\", JIM_ERRMSG)) return JIM_ERR;" +lappend lines "\treturn Jim_EvalSource(interp, \"$basename\", 1, [join $sourcelines \n]);" +lappend lines "\}" + +puts [join $lines \n] diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-index b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-index new file mode 100755 index 0000000..8dba920 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-index @@ -0,0 +1,70 @@ +#!/usr/bin/env tclsh +# vim:se syn=tcl: + +set filename [lindex $argv 0] +set f [open $filename] + +# Read the file looking for command definitions +set lines {} +set commands {} +array set cdict {} +set c 0 + +while {[gets $f buf] >= 0} { + if {[string match "~~*" $buf]} { + if {[string match "*:*" $prev]} { + incr c + set target cmd_$c + set lines [linsert $lines end-1 "\[\[$target\]\]"] + } else { + set target _$prev + } + foreach cmd [split $prev ":,"] { + set cmd [string trim $cmd] + if {[regexp {^[a-z.]+$} $cmd]} { + lappend commands [list $cmd $target] + set cdict($cmd) $target + } + } + } + lappend lines $buf + set prev $buf +} +close $f + +# Build the command index in the list: $index +lappend index {[frame="none",grid="none"]} +lappend index {|=========================} +set i 0 +set row {} +foreach command [lsort $commands] { + lassign $command cmd target + + append row "|<<$target,*`$cmd`*>> " + incr i + if {$i % 8 == 0} { + lappend index $row + set row {} + } +} +while {$i % 8 != 0} { + incr i + append row "| " +} +lappend index $row +lappend index {|=========================} + +# Map all `cmd` to <<$target,`cmd`>> +set mapping {} +foreach c [array names cdict] { + lappend mapping `$c` <<$cdict($c),*`$c`*>> + lappend mapping "`$c " "<<$cdict($c),*`$c`*>> `" +} + +# And the command index +lappend mapping @INSERTINDEX@ [join $index \n] + +# Output the result +foreach line $lines { + puts [string map $mapping $line] +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl new file mode 100755 index 0000000..9185e77 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/make-load-static-exts.tcl @@ -0,0 +1,48 @@ +#!/usr/bin/env tclsh + +# Usage: make-load-static-exts extname ... >load-static-exts.c + +# Creates load-static-exts.c based on the configured static extensions + +# There are some dependencies on static extensions which require +# a certain load order. Do this by setting priorities and sorting. + +array set pri { + stdlib 0 + readdir 1 + glob 2 + oo 1 + tree 2 + pack 1 + binary 2 +} + +foreach i $argv { + set p 1 + if {[info exists pri($i)]} { + set p $pri($i) + } + lappend exts [list $p $i] +} +set exts [lsort $exts] + +puts { +/* autogenerated - do not edit */ +#include "jim.h" +#include "jimautoconf.h" +int Jim_InitStaticExtensions(Jim_Interp *interp) +} +puts \{ + +foreach e $exts { + set ext [lindex $e 1] + puts "\textern int Jim_${ext}Init(Jim_Interp *);" +} +foreach e $exts { + set ext [lindex $e 1] + puts "\tJim_${ext}Init(interp);" +} + +puts "\treturn JIM_OK;" + +puts \} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl new file mode 100755 index 0000000..4b5ec3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/parse-unidata.tcl @@ -0,0 +1,64 @@ +#!/usr/bin/env tclsh + +# Generate UTF-8 case mapping tables +# +# (c) 2010 Steve Bennett <steveb@workware.net.au> +# +# See LICENCE for licence details. +#/ + +# Parse the unicode data from: http://unicode.org/Public/UNIDATA/UnicodeData.txt +# to generate case mapping tables + +set f [open [lindex $argv 0]] +set extoff 0 +puts "static const struct casemap unicode_case_mapping\[\] = \{" +while {[gets $f buf] >= 0} { + foreach {code name class x x x x x x x x x upper lower} [split $buf ";"] break + set code 0x$code + if {$code <= 0x7f} { + continue + } + if {$code > 0xffff} { + break + } + if {$class ne "Lu" && $class ne "Ll"} { + continue + } + if {$upper eq ""} { + set upper $code + } else { + set upper 0x$upper + } + if {$lower eq ""} { + set lower $code + } else { + set lower 0x$lower + } + if {$upper == $code && $lower == $code} { + continue + } + set l [expr {$lower - $code}] + set u [expr {$upper - $code}] + if {abs($u) > 127 || abs($l) > 127} { + # Can't encode both in one byte, so use indirection + lappend jumptable $code $lower $upper + set l -128 + set u $extoff + incr extoff + if {$extoff > 0xff} { + error "Too many entries in the offset table!" + } + } + set entry [string tolower "$code, $l, $u"] + puts " { $entry }," +} +close $f +puts "\};\n" + +# Now the jump table +puts "static const struct caseextmap unicode_extmap\[\] = \{" +foreach {c l u} $jumptable { + puts " { $l, $u }," +} +puts "\};\n" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/regtest.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/regtest.tcl new file mode 100755 index 0000000..de796d9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/regtest.tcl @@ -0,0 +1,158 @@ +# REGTEST 1 +# 27Jan2005 - SIGSEGV for bug on Jim_DuplicateObj(). + +for {set i 0} {$i < 100} {incr i} { + set a "x" + lappend a n +} +puts "TEST 1 PASSED" + +# REGTEST 2 +# 29Jan2005 - SEGFAULT parsing script composed of just one comment. +eval {#foobar} +puts "TEST 2 PASSED" + +# REGTEST 3 +# 29Jan2005 - "Error in Expression" with correct expression +set x 5 +expr {$x-5} +puts "TEST 3 PASSED" + +# REGTEST 4 +# 29Jan2005 - SIGSEGV when run this code, due to expr's bug. +proc fibonacci {x} { + if {$x <= 1} { + expr 1 + } else { + expr {[fibonacci [expr {$x-1}]] + [fibonacci [expr {$x-2}]]} + } +} +fibonacci 6 +puts "TEST 4 PASSED" + +# REGTEST 5 +# 06Mar2005 - This looped forever... +for {set i 0} {$i < 10} {incr i} {continue} +puts "TEST 5 PASSED" + +# REGTEST 6 +# 07Mar2005 - Unset create variable + dict is using dict syntax sugar at +# currently non-existing variable +catch {unset thisvardoesnotexists(thiskeytoo)} +if {[catch {set thisvardoesnotexists}] == 0} { + puts "TEST 6 FAILED - unset created dict for non-existing variable" + break +} +puts "TEST 6 PASSED" + +# REGTEST 7 +# 04Nov2008 - variable parsing does not eat last brace +set a 1 +list ${a} +puts "TEST 7 PASSED" + +# REGTEST 8 +# 04Nov2008 - string toupper/tolower do not convert to string rep +string tolower [list a] +string toupper [list a] +puts "TEST 8 PASSED" + +# REGTEST 9 +# 04Nov2008 - crash on exit when replacing Tcl proc with C command. +# Requires the clock extension to be built as a loadable module. +proc clock {args} {} +catch {package require clock} +# Note, crash on exit, so don't say we passed! + +# REGTEST 10 +# 05Nov2008 - incorrect lazy expression evaluation with unary not +expr {1 || !0} +puts "TEST 10 PASSED" + +# REGTEST 11 +# 14 Feb 2010 - access static variable in deleted proc +proc a {} {{x 1}} { rename a ""; incr x } +a +puts "TEST 11 PASSED" + +# REGTEST 12 +# 13 Sep 2010 - reference with invalid tag +set a b[ref value "tag name"] +getref [string range $a 1 end] +puts "TEST 12 PASSED" + +# REGTEST 13 +# 14 Sep 2010 - parse list with trailing backslash +set x "switch -0 \$on \\" +lindex $x 1 +puts "TEST 13 PASSED" + +# REGTEST 14 +# 14 Sep 2010 - command expands to nothing +eval "{*}{}" +puts "TEST 14 PASSED" + +# REGTEST 15 +# 24 Feb 2010 - bad reference counting of the stack trace in 'error' +proc a {msg stack} { + tailcall error $msg $stack +} +catch {fail} msg opts +catch {a $msg $opts(-errorinfo)} + +# REGTEST 16 +# 24 Feb 2010 - rename the current proc +# Leaves unfreed objects on the stack +proc a {} { rename a newa} +a + +# REGTEST 17 +# 26 Nov 2010 - crashes on invalid dict sugar +catch {eval {$x(}} +puts "TEST 17 PASSED" + +# REGTEST 18 +# 12 Apr 2011 - crashes on unset for loop var +catch { + for {set i 0} {$i < 5} {incr i} {unset i} +} +puts "TEST 18 PASSED" + +# REGTEST 19 +# 25 May 2011 - crashes with double colon +catch { + expr {5 ne ::} +} +puts "TEST 19 PASSED" + +# REGTEST 20 +# 26 May 2011 - infinite recursion +proc a {} { global ::blah; set ::blah test } +a +puts "TEST 20 PASSED" + +# REGTEST 21 +# 26 May 2011 - infinite loop with null byte in subst +subst "abc\0def" +puts "TEST 21 PASSED" + +# REGTEST 22 +# 21 June 2011 - crashes on lappend to to value with script rep +set x rand +eval $x +lappend x b +puts "TEST 22 PASSED" + +# REGTEST 23 +# 27 July 2011 - unfreed objects on exit +catch { + set x abc + subst $x + regexp $x $x +} +# Actually, the test passes if no objects leaked on exit +puts "TEST 23 PASSED" + +# TAKE THE FOLLOWING puts AS LAST LINE + +puts "--- ALL TESTS PASSED ---" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl new file mode 100755 index 0000000..cdd78d4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/rlprompt.tcl @@ -0,0 +1,45 @@ +# Readline-based interactive shell for Jim +# Copyright(C) 2005 Salvatore Sanfilippo <antirez@invece.org> +# +# In order to automatically have readline-editing features +# put this in your $HOME/.jimrc +# +# if {$jim_interactive} { +# if {[catch {package require rlprompt}] == 0} { +# rlprompt.shell +# } +# } +package require readline + +proc rlprompt.shell {} { + puts "Readline shell loaded" + puts "Welcome to Jim [info version]!" + set prompt ". " + set buf "" + while 1 { + set line [readline.readline $prompt] + + if {[string length $line] == 0} { + continue + } + if {$buf eq ""} { + set buf $line + } else { + append buf \n $line + } + if {![info complete $buf]} { + set prompt "> " + continue + } + readline.addhistory $buf + + catch { + uplevel #0 $buf + } error + if {$error ne ""} { + puts $error + } + set buf "" + set prompt ". " + } +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl new file mode 100755 index 0000000..3abeb3e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/stdlib.tcl @@ -0,0 +1,150 @@ +# Create a single word alias (proc) for one or more words +# e.g. alias x info exists +# if {[x var]} ... +proc alias {name args} { + set prefix $args + proc $name args prefix { + tailcall {*}$prefix {*}$args + } +} + +# Creates an anonymous procedure +proc lambda {arglist args} { + set name [ref {} function lambda.finalizer] + tailcall proc $name $arglist {*}$args +} + +proc lambda.finalizer {name val} { + rename $name {} +} + +# Like alias, but creates and returns an anonyous procedure +proc curry {args} { + set prefix $args + lambda args prefix { + tailcall {*}$prefix {*}$args + } +} + +# Returns the given argument. +# Useful with 'local' as follows: +# proc a {} {...} +# local function a +# +# set x [lambda ...] +# local function $x +# +proc function {value} { + return $value +} + +# Tcl 8.5 lassign +proc lassign {list args} { + # in case the list is empty... + lappend list {} + uplevel 1 [list foreach $args $list break] + lrange $list [llength $args] end-1 +} + +# Returns a list of proc filename line ... +# with 3 entries for each stack frame (proc), +# (deepest level first) +proc stacktrace {} { + set trace {} + foreach level [range 1 [info level]] { + lassign [info frame -$level] p f l + lappend trace $p $f $l + } + return $trace +} + +# Returns a human-readable version of a stack trace +proc stackdump {stacktrace} { + set result {} + set count 0 + foreach {l f p} [lreverse $stacktrace] { + if {$count} { + append result \n + } + incr count + if {$p ne ""} { + append result "in procedure '$p' " + if {$f ne ""} { + append result "called " + } + } + if {$f ne ""} { + append result "at file \"$f\", line $l" + } + } + return $result +} + +# Sort of replacement for $::errorInfo +# Usage: errorInfo error ?stacktrace? +proc errorInfo {msg {stacktrace ""}} { + if {$stacktrace eq ""} { + set stacktrace [info stacktrace] + } + lassign $stacktrace p f l + if {$f ne ""} { + set result "Runtime Error: $f:$l: " + } + append result "$msg\n" + append result [stackdump $stacktrace] + + # Remove the trailing newline + string trim $result +} + +# Finds the current executable by searching along the path +# Returns the empty string if not found. +proc {info nameofexecutable} {} { + if {[info exists ::jim_argv0]} { + if {[string match "*/*" $::jim_argv0]} { + return [file join [pwd] $::jim_argv0] + } + foreach path [split [env PATH ""] $::tcl_platform(pathSeparator)] { + set exec [file join [pwd] $path $::jim_argv0] + if {[file executable $exec]} { + return $exec + } + } + } + return "" +} + +# Script-based implementation of 'dict with' +proc {dict with} {dictVar args script} { + upvar $dictVar dict + set keys {} + foreach {n v} [dict get $dict {*}$args] { + upvar $n var_$n + set var_$n $v + lappend keys $n + } + catch {uplevel 1 $script} msg opts + if {[info exists dict] && [dict exists $dict {*}$args]} { + foreach n $keys { + if {[info exists var_$n]} { + dict set dict {*}$args $n [set var_$n] + } else { + dict unset dict {*}$args $n + } + } + } + return {*}$opts $msg +} + +# Script-based implementation of 'dict merge' +# This won't get called in the trivial case of no args +proc {dict merge} {dict args} { + foreach d $args { + # Check for a valid dict + dict size $d + foreach {k v} $d { + dict set dict $k $v + } + } + return $dict +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms new file mode 100755 index 0000000..f1dcaa5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tcl.license.terms @@ -0,0 +1,40 @@ +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl new file mode 100755 index 0000000..8e5b128 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tclcompat.tcl @@ -0,0 +1,279 @@ +# (c) 2008 Steve Bennett <steveb@workware.net.au> +# +# Loads some Tcl-compatible features. +# I/O commands, case, lassign, parray, errorInfo, ::tcl_platform, ::env +# try, throw, file copy, file delete -force + +# Set up the ::env array +set env [env] + +if {[info commands stdout] ne ""} { + # Tcl-compatible I/O commands + foreach p {gets flush close eof seek tell} { + proc $p {chan args} {p} { + tailcall $chan $p {*}$args + } + } + unset p + + # puts is complicated by -nonewline + # + proc puts {{-nonewline {}} {chan stdout} msg} { + if {${-nonewline} ni {-nonewline {}}} { + tailcall ${-nonewline} puts $msg + } + tailcall $chan puts {*}${-nonewline} $msg + } + + # read is complicated by -nonewline + # + # read chan ?maxchars? + # read -nonewline chan + proc read {{-nonewline {}} chan} { + if {${-nonewline} ni {-nonewline {}}} { + tailcall ${-nonewline} read {*}${chan} + } + tailcall $chan read {*}${-nonewline} + } + + proc fconfigure {f args} { + foreach {n v} $args { + switch -glob -- $n { + -bl* { + $f ndelay $v + } + -bu* { + $f buffering $v + } + -tr* { + # Just ignore -translation + } + default { + return -code error "fconfigure: unknown option $n" + } + } + } + } +} + +# case var ?in? pattern action ?pattern action ...? +proc case {var args} { + # Skip dummy parameter + if {[lindex $args 0] eq "in"} { + set args [lrange $args 1 end] + } + + # Check for single arg form + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + # Check for odd number of args + if {[llength $args] % 2 != 0} { + return -code error "extra case pattern with no body" + } + + # Internal function to match a value agains a list of patterns + local proc case.checker {value pattern} { + string match $pattern $value + } + + foreach {value action} $args { + if {$value eq "default"} { + set do_action $action + continue + } elseif {[lsearch -bool -command case.checker $value $var]} { + set do_action $action + break + } + } + + if {[info exists do_action]} { + set rc [catch [list uplevel 1 $do_action] result opts] + if {$rc} { + incr opts(-level) + } + return {*}$opts $result + } +} + +# fileevent isn't needed in Jim, but provide it for compatibility +proc fileevent {args} { + tailcall {*}$args +} + +# Second, option argument is a glob pattern +# Third, optional argument is a "putter" function +# +proc parray {arrayname {pattern *} {puts puts}} { + upvar $arrayname a + + set max 0 + foreach name [array names a $pattern]] { + if {[string length $name] > $max} { + set max [string length $name] + } + } + incr max [string length $arrayname] + incr max 2 + foreach name [lsort [array names a $pattern]] { + $puts [format "%-${max}s = %s" $arrayname\($name\) $a($name)] + } +} + +# Implements 'file copy' - single file mode only +proc {file copy} {{force {}} source target} { + try { + if {$force ni {{} -force}} { + error "bad option \"$force\": should be -force" + } + + set in [open $source] + + if {$force eq "" && [file exists $target]} { + $in close + error "error copying \"$source\" to \"$target\": file already exists" + } + set out [open $target w] + $in copyto $out + $out close + } on error {msg opts} { + incr opts(-level) + return {*}$opts $msg + } finally { + catch {$in close} + } +} + +# 'open "|..." ?mode?" will invoke this wrapper around exec/pipe +# Note that we return a lambda which also provides the 'pid' command +proc popen {cmd {mode r}} { + lassign [socket pipe] r w + try { + if {[string match "w*" $mode]} { + lappend cmd <@$r & + set pids [exec {*}$cmd] + $r close + set f $w + } else { + lappend cmd >@$w & + set pids [exec {*}$cmd] + $w close + set f $r + } + lambda {cmd args} {f pids} { + if {$cmd eq "pid"} { + return $pids + } + if {$cmd eq "close"} { + $f close + # And wait for the child processes to complete + foreach p $pids { os.wait $p } + return + } + tailcall $f $cmd {*}$args + } + } on error {error opts} { + $r close + $w close + error $error + } +} + +# A wrapper around 'pid' which can return the pids for 'popen' +local proc pid {{chan {}}} { + if {$chan eq ""} { + tailcall upcall pid + } + if {[catch {$chan tell}]} { + return -code error "can not find channel named \"$chan\"" + } + if {[catch {$chan pid} pids]} { + return "" + } + return $pids +} + +# try/on/finally conceptually similar to Tcl 8.6 +# +# Usage: try ?catchopts? script ?onclause ...? ?finallyclause? +# +# Where: +# onclause is: on codes {?resultvar? ?optsvar?} script +# +# codes is: a list of return codes (ok, error, etc. or integers), or * for any +# +# finallyclause is: finally script +# +# +# Where onclause is: on codes {?resultvar? ?optsvar?} +proc try {args} { + set catchopts {} + while {[string match -* [lindex $args 0]]} { + set args [lassign $args opt] + if {$opt eq "--"} { + break + } + lappend catchopts $opt + } + if {[llength $args] == 0} { + return -code error {wrong # args: should be "try ?options? script ?argument ...?"} + } + set args [lassign $args script] + set code [catch -eval {*}$catchopts [list uplevel 1 $script] msg opts] + + set handled 0 + + foreach {on codes vars script} $args { + switch -- $on \ + on { + if {!$handled && ($codes eq "*" || [info returncode $code] in $codes)} { + lassign $vars msgvar optsvar + if {$msgvar ne ""} { + upvar $msgvar hmsg + set hmsg $msg + } + if {$optsvar ne ""} { + upvar $optsvar hopts + set hopts $opts + } + # Override any body result + set code [catch [list uplevel 1 $script] msg opts] + incr handled + } + } \ + finally { + set finalcode [catch [list uplevel 1 $codes] finalmsg finalopts] + if {$finalcode} { + # Override any body or handler result + set code $finalcode + set msg $finalmsg + set opts $finalopts + } + break + } \ + default { + return -code error "try: expected 'on' or 'finally', got '$on'" + } + } + + if {$code} { + incr opts(-level) + return {*}$opts $msg + } + return $msg +} + +# Generates an exception with the given code (ok, error, etc. or an integer) +# and the given message +proc throw {code {msg ""}} { + return -code $code $msg +} + +# Helper for "file delete -force" +proc {file delete force} {path} { + foreach e [readdir $path] { + file delete -force $path/$e + } + file delete $path +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tree.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tree.tcl new file mode 100755 index 0000000..01fc167 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/tree.tcl @@ -0,0 +1,219 @@ +# Conceptually compatible with tcllib ::struct::tree +# but uses an object based interface. +# To mimic tcllib, do: +# rename [tree] mytree + +package require oo + +# set pt [tree] +# +# Create a tree +# This automatically creates a node named "root" +# +# $pt destroy +# +# Destroy the tree and all it's nodes +# +# $pt set <nodename> <key> <value> +# +# Set the value for the given key +# +# $pt lappend <nodename> <key> <value> ... +# +# Append to the (list) value(s) for the given key, or set if not yet set +# +# $pt keyexists <nodename> <key> +# +# Returns 1 if the given key exists +# +# $pt get <nodename> <key> +# +# Returns the value associated with the given key +# +# $pt getall <nodename> +# +# Returns the entire attribute dictionary associated with the given key +# +# $pt depth <nodename> +# +# Returns the depth of the given node. The depth of "root" is 0. +# +# $pt parent <nodename> +# +# Returns the name of the parent node, or "" for the root node. +# +# $pt numchildren <nodename> +# +# Returns the number of child nodes. +# +# $pt children <nodename> +# +# Returns a list of the child nodes. +# +# $pt next <nodename> +# +# Returns the next sibling node, or "" if none. +# +# $pt insert <nodename> ?index? +# +# Add a new child node to the given node. +# THe default index is "end" +# Returns the name of the newly added node +# +# $pt walk <nodename> dfs|bfs {actionvar nodevar} <code> +# +# Walks the tree starting from the given node, either breadth first (bfs) +# depth first (dfs). +# The value "enter" or "exit" is stored in variable $actionvar +# The name of each node is stored in $nodevar. +# The script $code is evaluated twice for each node, on entry and exit. +# +# $pt dump +# +# Dumps the tree contents to stdout + +#------------------------------------------ +# Internal implementation. +# The tree class has 4 instance variables. +# - tree is a dictionary. key=node, value=node value dictionary +# - parent is a dictionary. key=node, value=parent of this node +# - children is a dictionary. key=node, value=list of child nodes for this node +# - nodeid is an integer which increments to give each node a unique id + +# Construct a tree with a single root node with no parent and no children +class tree { + tree {root {}} + parents {root {}} + children {root {}} + nodeid 0 +} + +# Simply walk up the tree to get the depth +tree method depth {node} { + set depth 0 + while {$node ne "root"} { + incr depth + set node [dict get $parents $node] + } + return $depth +} + +tree method parent {node} { + dict get $parents $node +} + +tree method children {node} { + dict get $children $node +} + +tree method numchildren {node} { + llength [dict get $children $node] +} + +tree method next {node} { + # My siblings are my parents children + set siblings [dict get $children [dict get $parents $node]] + # Find me + set i [lsearch $siblings $node] + incr i + lindex $siblings $i +} + +tree method set {node key value} { + dict set tree $node $key $value + return $value +} + +tree method get {node key} { + dict get $tree $node $key +} + +tree method keyexists {node key} { + dict exists $tree $node $key +} + +tree method getall {node} { + dict get $tree $node +} + +tree method insert {node {index end}} { + + # Make a new node and add it to the tree + set childname node[incr nodeid] + dict set tree $childname {} + + # The new node has no children + dict set children $childname {} + + # Set the parent + dict set parents $childname $node + + # And add it as a child + set nodes [dict get $children $node] + dict set children $node [linsert $nodes $index $childname] + + return $childname +} + +tree method lappend {node key args} { + if {[dict exists $tree $node $key]} { + set result [dict get $tree $node $key] + } + lappend result {*}$args + dict set tree $node $key $result + return $result +} + +# $tree walk node bfs|dfs {action loopvar} <code> +# +tree method walk {node type vars code} { + # set up vars + lassign $vars actionvar namevar + + set n $node + + if {$type ne "child"} { + upvar 2 $namevar name $actionvar action + + # Enter this node + set name $node + set action enter + + uplevel 2 $code + } + + if {$type eq "dfs"} { + # Depth-first so do the children + foreach child [$self children $n] { + uplevel 2 [list $self walk $child $type $vars $code] + } + } elseif {$type ne "none"} { + # Breadth-first so do the children to one level only + foreach child [$self children $n] { + uplevel 2 [list $self walk $child none $vars $code] + } + + # Now our grandchildren + foreach child [$self children $n] { + uplevel 2 [list $self walk $child child $vars $code] + } + } + + if {$type ne "child"} { + # Exit this node + set name $node + set action exit + + uplevel 2 $code + } +} + +tree method dump {} { + $self walk root dfs {action n} { + set indent [string repeat " " [$self depth $n]] + if {$action eq "enter"} { + puts "$indent$n ([$self getall $n])" + } + } + puts "" +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.c new file mode 100755 index 0000000..a81b3de --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.c @@ -0,0 +1,192 @@ +/** + * UTF-8 utility functions + * + * (c) 2010 Steve Bennett <steveb@workware.net.au> + * + * See LICENCE for licence details. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#include "utf8.h" + +/* This one is always implemented */ +int utf8_fromunicode(char *p, unsigned short uc) +{ + if (uc <= 0x7f) { + *p = uc; + return 1; + } + else if (uc <= 0x7ff) { + *p++ = 0xc0 | ((uc & 0x7c0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 2; + } + else { + *p++ = 0xe0 | ((uc & 0xf000) >> 12); + *p++ = 0x80 | ((uc & 0xfc0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 3; + } +} + +#if defined(JIM_UTF8) && !defined(JIM_BOOTSTRAP) +int utf8_charlen(int c) +{ + if ((c & 0x80) == 0) { + return 1; + } + if ((c & 0xe0) == 0xc0) { + return 2; + } + if ((c & 0xf0) == 0xe0) { + return 3; + } + if ((c & 0xf8) == 0xf0) { + return 4; + } + /* Invalid sequence */ + return -1; +} + +int utf8_strlen(const char *str, int bytelen) +{ + int charlen = 0; + if (bytelen < 0) { + bytelen = strlen(str); + } + while (bytelen) { + int c; + int l = utf8_tounicode(str, &c); + charlen++; + str += l; + bytelen -= l; + } + return charlen; +} + +int utf8_index(const char *str, int index) +{ + const char *s = str; + while (index--) { + int c; + s += utf8_tounicode(s, &c); + } + return s - str; +} + +int utf8_charequal(const char *s1, const char *s2) +{ + int c1, c2; + + utf8_tounicode(s1, &c1); + utf8_tounicode(s2, &c2); + + return c1 == c2; +} + +int utf8_prev_len(const char *str, int len) +{ + int n = 1; + + assert(len > 0); + + /* Look up to len chars backward for a start-of-char byte */ + while (--len) { + if ((str[-n] & 0x80) == 0) { + /* Start of a 1-byte char */ + break; + } + if ((str[-n] & 0xc0) == 0xc0) { + /* Start of a multi-byte char */ + break; + } + n++; + } + return n; +} + +int utf8_tounicode(const char *str, int *uc) +{ + unsigned const char *s = (unsigned const char *)str; + + if (s[0] < 0xc0) { + *uc = s[0]; + return 1; + } + if (s[0] < 0xe0) { + if ((s[1] & 0xc0) == 0x80) { + *uc = ((s[0] & ~0xc0) << 6) | (s[1] & ~0x80); + return 2; + } + } + else if (s[0] < 0xf0) { + if (((str[1] & 0xc0) == 0x80) && ((str[2] & 0xc0) == 0x80)) { + *uc = ((s[0] & ~0xe0) << 12) | ((s[1] & ~0x80) << 6) | (s[2] & ~0x80); + return 3; + } + } + + /* Invalid sequence, so just return the byte */ + *uc = *s; + return 1; +} + +struct casemap { + unsigned short code; /* code point */ + signed char lowerdelta; /* add for lowercase, or if -128 use the ext table */ + signed char upperdelta; /* add for uppercase, or offset into the ext table */ +}; + +/* Extended table for codepoints where |delta| > 127 */ +struct caseextmap { + unsigned short lower; + unsigned short upper; +}; + +/* Generated mapping tables */ +#include "_unicode_mapping.c" + +#define NUMCASEMAP sizeof(unicode_case_mapping) / sizeof(*unicode_case_mapping) + +static int cmp_casemap(const void *key, const void *cm) +{ + return *(int *)key - (int)((const struct casemap *)cm)->code; +} + +static int utf8_map_case(int uc, int upper) +{ + const struct casemap *cm = bsearch(&uc, unicode_case_mapping, NUMCASEMAP, sizeof(*unicode_case_mapping), cmp_casemap); + + if (cm) { + if (cm->lowerdelta == -128) { + uc = upper ? unicode_extmap[cm->upperdelta].upper : unicode_extmap[cm->upperdelta].lower; + } + else { + uc += upper ? cm->upperdelta : cm->lowerdelta; + } + } + return uc; +} + +int utf8_upper(int uc) +{ + if (isascii(uc)) { + return toupper(uc); + } + return utf8_map_case(uc, 1); +} + +int utf8_lower(int uc) +{ + if (isascii(uc)) { + return tolower(uc); + } + + return utf8_map_case(uc, 0); +} + +#endif /* JIM_BOOTSTRAP */ diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.h new file mode 100755 index 0000000..9ada93f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/jim/utf8.h @@ -0,0 +1,110 @@ +#ifndef UTF8_UTIL_H +#define UTF8_UTIL_H +/** + * UTF-8 utility functions + * + * (c) 2010 Steve Bennett <steveb@workware.net.au> + * + * See LICENCE for licence details. + */ +#include <jim-config.h> + +/** + * Converts the given unicode codepoint (0 - 0xffff) to utf-8 + * and stores the result at 'p'. + * + * Returns the number of utf-8 characters (1-3). + */ +int utf8_fromunicode(char *p, unsigned short uc); + +#ifndef JIM_UTF8 +#include <ctype.h> + +/* No utf-8 support. 1 byte = 1 char */ +#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) +#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) +#define utf8_upper(C) toupper(C) +#define utf8_lower(C) tolower(C) +#define utf8_index(C, I) (I) +#define utf8_charlen(C) 1 +#define utf8_prev_len(S, L) 1 + +#else +#if !defined(JIM_BOOTSTRAP) +/** + * Returns the length of the utf-8 sequence starting with 'c'. + * + * Returns 1-4, or -1 if this is not a valid start byte. + * + * Note that charlen=4 is not supported by the rest of the API. + */ +int utf8_charlen(int c); + +/** + * Returns the number of characters in the utf-8 + * string of the given byte length. + * + * Any bytes which are not part of an valid utf-8 + * sequence are treated as individual characters. + * + * The string *must* be null terminated. + * + * Does not support unicode code points > \uffff + */ +int utf8_strlen(const char *str, int bytelen); + +/** + * Returns the byte index of the given character in the utf-8 string. + * + * The string *must* be null terminated. + * + * This will return the byte length of a utf-8 string + * if given the char length. + */ +int utf8_index(const char *str, int charindex); + +/** + * Returns the unicode codepoint corresponding to the + * utf-8 sequence 'str'. + * + * Stores the result in *uc and returns the number of bytes + * consumed. + * + * If 'str' is null terminated, then an invalid utf-8 sequence + * at the end of the string will be returned as individual bytes. + * + * If it is not null terminated, the length *must* be checked first. + * + * Does not support unicode code points > \uffff + */ +int utf8_tounicode(const char *str, int *uc); + +/** + * Returns the number of bytes before 'str' that the previous + * utf-8 character sequence starts (which may be the middle of a sequence). + * + * Looks back at most 'len' bytes backwards, which must be > 0. + * If no start char is found, returns -len + */ +int utf8_prev_len(const char *str, int len); + +/** + * Returns the upper-case variant of the given unicode codepoint. + * + * Does not support unicode code points > \uffff + */ +int utf8_upper(int uc); + +/** + * Returns the lower-case variant of the given unicode codepoint. + * + * NOTE: Use utf8_upper() in preference for case-insensitive matching. + * + * Does not support unicode code points > \uffff + */ +int utf8_lower(int uc); +#endif /* JIM_BOOTSTRAP */ + +#endif + +#endif diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/make_string.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/make_string.tcl new file mode 100755 index 0000000..5a1b5ff --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/make_string.tcl @@ -0,0 +1,31 @@ +#!/usr/bin/env tclsh + +# (c) Josua Dietze 2012 +# +# Usage: make_string.tcl source.tcl >jim-source.c + +# Converts a Tcl source file into C source suitable +# for using as an embedded script. + +set source [lindex $argv 0] + +if {![string match *.tcl $source]} { + error "Source $source is not a .tcl file" +} + +# Read the Tcl source and convert to C macro +set sourcelines {} +set f [open $source] +while {[gets $f buf] >= 0} { + # Remove comment lines + regsub {^[ \t]*#.*$} $buf "" buf + # Remove leading whitespaces + set buf [string trimleft $buf] + # Escape quotes and backlashes + set buf [string map [list \\ \\\\ \" \\"] $buf] + if [string length $buf] { + lappend sourcelines "$buf\\n" + } +} +close $f +puts "#define RAW \"[join $sourcelines ""]\"" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf new file mode 100755 index 0000000..570ca65 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb-modeswitch-upstart.conf @@ -0,0 +1,5 @@ +start on usb-modeswitch-upstart +task +script + exec /usr/sbin/usb_modeswitch_dispatcher --switch-upstart $UMS_PARAM +end script diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 new file mode 100755 index 0000000..fecac7c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.1 @@ -0,0 +1,172 @@ +.TH "USB_MODESWITCH" "1" +.SH "NAME" +usb_modeswitch - control the mode of 'multi-state' USB devices +.SH "SYNOPSIS" +.PP +\fBusb_modeswitch\fR [\fB\-heWQDIvpVPmM23rwKdHSOBGTNALnsRiuagft\fP] [\fB\-c \fIfilename\fP] +.SH "DESCRIPTION" +.PP +Several new USB devices have their proprietary Windows drivers onboard, +most of them WWAN and WLAN dongles. When plugged in for the first time, +they act like a flash storage and start installing the Windows driver from +there. If the driver is already installed, it makes the storage device +disappear and a new device, mainly composite with modem ports, shows up. +.PP +On Linux, in most cases the drivers are available as kernel modules, +such as "usbserial" or "option". However, the device initially binds to +"usb-storage" by default. \fBusb_modeswitch\fR can then send a provided bulk +message (most likely a mass storage command) to the device; this message +has to be determined by analyzing the actions of the Windows driver. +.PP +In some cases, USB control commands are used for switching. These cases are +handled by custom functions, and no bulk message needs to be provided. +.PP +Usually, the program is distributed with a set of configurations for many +known devices, which allows a fully automatic handling of a device upon +insertion, made possible by combining usb_modeswitch with the wrapper script +\fBusb_modeswitch_dispatcher\fR which is launched by the udev daemon. +.PP +Note that \fBusb_modeswitch\fR itself has no specific Linux dependencies. + +.SH "OPTIONS" +.PP +This program follows the usual GNU command line syntax, +with long options starting with two dashes ('--'). A summary of +options is included below. +.IP "\fB-h\fP \fB\-\-help\fP " 10 +Show summary of options. +.IP "\fB-e\fP \fB\-\-version\fP " 10 +Print version information and exit +.IP "\fB-v\fP \fB\-\-default-vendor NUM\fP " 10 +Vendor ID to look for (mandatory), usually given as hex number (example: 0x12d1). +Each USB device is identified by a number +officialy assigned to the vendor by the USB association and a number for the +respective model (product ID) chosen by the vendor +.IP "\fB-p\fP \fB\-\-default-product NUM\fP " 10 +Product ID to look for (mandatory) +.IP "\fB-V\fP \fB\-\-target-vendor NUM\fP " 10 +Target vendor ID. When given will be searched for and detected initially +for information purposes. If success checking (option \-s) is active, +providing target IDs (vendor/product) or target class is recommended +.IP "\fB-j\fP \fB\-\-find-mbim\fP " 10 +Return configuration number with MBIM interface and exit. +.IP "\fB-P\fP \fB\-\-target-product NUM\fP " 10 +Target product ID +.IP "\fB-b\fP \fB\-\-bus-num NUM\fP " 10 +.IP "\fB-g\fP \fB\-\-device-num NUM\fP " 10 +If bus and device number are provided, the handling of a specific device on +a specific USB port is guaranteed, in contrast to using only the USB ID. This +is important if there are multiple similar devices on a system +.IP "\fB-C\fP \fB\-\-target-class NUM\fP " 10 +Target Device Class according to the USB specification. Some devices keep +their original vendor/product ID after successful switching. To prevent +them from being treated again, the device class can be checked. +For unswitched devices it is always 8 (storage class), for switched +modems it is often 0xff (vendor specific). In composite modes, +the class of the first interface is watched +.IP "\fB-m\fP \fB\-\-message-endpoint NUM\fP " 10 +A specific endpoint to use for data transfers. Only for testing purposes; usually +endpoints are determined from the device attributes +.IP "\fB-M\fP \fB\-\-message-content STRING\fP " 10 +A bulk message to send as a switching command. Provided as a hexadecimal string +.IP "\fB-2, -3\fP \fB\-\-message-content2, \-\-message-content3 STRING\fP " 10 +Additional bulk messages to send as switching commands. Provided as hexadecimal strings. +When used with mass storage commands, setting \fB\-\-need-response\fR is +strongly advised to comply with specifications and to avoid likely errors +.IP "\fB-w\fP \fB\-\-release-delay NUM\fP " 10 +After issuing all bulk messages, wait for NUM milliseconds before releasing the interface. +Required for some modems on older systems (especially after an EJECT message) +.IP "\fB-n\fP \fB\-\-need-response\fP " 10 +Obsolete. CSW is always attempted to being read after mass storage transfers. No downside +.IP "\fB-r\fP \fB\-\-response-endpoint NUM\fP " 10 +Try to read the response to a storage command from there. Only for testing purposes; +usually endpoints are determined from the device attributes +.IP "\fB-K\fP \fB\-\-std-eject\fP " 10 +Apply the standard SCSI sequence of "Allow Medium Removal" and +"Eject". Implies \fB-n\fP. One 'Message' can be added with \fB-M\fP +that will be transmitted after the eject sequence. Used by many modems +.IP "\fB-d\fP \fB\-\-detach-only\fP " 10 +Just detach the current driver. This is sufficient for some early +devices to switch successfully. Otherwise this feature can +be used as a 'scalpel' for special cases, like separating the +driver from individual interfaces +.IP "\fB-H\fP \fB\-\-huawei-mode\fP " 10 +Send a special control message used by older Huawei devices +.IP "\fB-J\fP \fB\-\-huawei-new-mode\fP " 10 +Send a specific bulk message used by all newer Huawei devices +.IP "\fB-S\fP \fB\-\-sierra-mode\fP " 10 +Send a special control message used by Sierra devices +.IP "\fB-G\fP \fB\-\-gct-mode\fP " 10 +Send a special control message used by GCT chipsets +.IP "\fB-T\fP \fB\-\-kobil-mode\fP " 10 +Send a special control message used by Kobil devices +.IP "\fB-N\fP \fB\-\-sequans-mode\fP " 10 +Send a special control message used by Sequans chipset +.IP "\fB-A\fP \fB\-\-mobileaction-mode\fP " 10 +Send a special control message used by the MobileAction device +.IP "\fB-B\fP \fB\-\-qisda-mode\fP " 10 +Send a special control message used by Qisda devices +.IP "\fB-E\fP \fB\-\-quanta-mode\fP " 10 +Send a special control message used by Quanta devices +.IP "\fB-F\fP \fB\-\-pantech-mode NUM\fP " 10 +Send a special control message used by Pantech devices. +Value NUM will be used in control message as 'wValue' +.IP "\fB-Z\fP \fB\-\-blackberry-mode\fP " 10 +Send a special control message used by some newer Blackberry devices +.IP "\fB-S\fP \fB\-\-option-mode\fP " 10 +Send a special control message used by all Option devices +.IP "\fB-O\fP \fB\-\-sony-mode\fP " 10 +Apply a special sequence used by Sony Ericsson devices. Implies option \--check-success +.IP "\fB-L\fP \fB\-\-cisco-mode\fP " 10 +Send a sequence of bulk messages used by Cisco devices +.IP "\fB-R\fP \fB\-\-reset-usb\fP " 10 +Send a USB reset command to the device. Can be combined with any switching +method or stand alone. It is always done as the last step of all device +interactions. +Few devices need it to complete the switching; apart from that it may be +useful during testing +.IP "\fB-c\fP \fB\-\-config-file FILENAME\fP " 10 +Use a specific config file. If any ID or switching options are given as +command line parameters, this option is ignored. +In that case all mandatory parameters have to be provided on +the command line +.IP "\fB-f\fP \fB\-\-long-config STRING\fP " 10 +Provide device details in config file syntax as a multiline string +on the command line +.IP "\fB-t\fP \fB\-\-stdinput\fP " 10 +Read the device details in config file syntax from standard input, e.g. redirected from +a command pipe (multiline text) +.IP "\fB-Q\fP \fB\-\-quiet\fP " 10 +Don't show progress or error messages +.IP "\fB-W\fP \fB\-\-verbose\fP " 10 +Print all settings before running and show libusb debug messages +.IP "\fB-D\fP \fB\-\-sysmode\fP " 10 +Changes the behaviour of the program slightly. A success message including the +effective target device ID is put out and a syslog notice is issued. Mainly for +integration with a wrapper script +.IP "\fB-s\fP \fB\-\-check-success NUM\fP " 10 +After switching, keep checking for the result up to max. NUM seconds. If target IDs +or target class were provided, their appearance indicates certain success. Otherwise +the disconnection of the original device is rated as likely proof +.IP "\fB-I\fP \fB\-\-inquire\fP " 10 +Obsolete. Formerly obtained SCSI attributes, now ignored +.IP "\fB-i\fP \fB\-\-interface NUM\fP " 10 +Select initial USB interface (default: 0). Only for testing purposes +.IP "\fB-u\fP \fB\-\-configuration NUM\fP " 10 +Select USB configuration (applied after any other possible switching actions) +.IP "\fB-a\fP \fB\-\-altsetting NUM\fP " 10 +Select alternative USB interface setting (applied after switching). Mainly +for testing +.SH "AUTHOR" +.PP +This manual page was originally written by Didier Raboud (didier@raboud.com) for +the \fBDebian\fP system. Additions made by Josua Dietze. Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 or any +later version published by the Free Software Foundation. + +.PP +The complete text of the current GNU General Public +License can be found in http://www.gnu.org/licenses/gpl.txt + +.\" last edited 2016-01-11 for version 2.3.0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.c new file mode 100755 index 0000000..ba5be82 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.c @@ -0,0 +1,2095 @@ +/* + Mode switching tool for controlling mode of 'multi-state' USB devices + Version 2.4.0, 2016/06/12 + + Copyright (C) 2007 - 2016 Josua Dietze (mail to "usb_admin" at the domain + of the home page; or write a personal message through the forum to "Josh". + NO SUPPORT VIA E-MAIL - please use the forum for that) + + Major contributions: + + Command line parsing, decent usage/config output/handling, bugfixes and advanced + options added by: + Joakim Wennergren + + TargetClass parameter implementation to support new Option devices/firmware: + Paul Hardwick (http://www.pharscape.org) + + Created with initial help from: + "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl) + + Config file parsing code borrowed from: + Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html) + + Hexstr2bin function borrowed from: + Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c") + + Other contributions: see README + + Device information contributors are named in the "device_reference.txt" file. See + homepage. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details: + + http://www.gnu.org/licenses/gpl.txt + +*/ + +/* Recommended tab size: 4 */ + +#define VERSION "2.4.0" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <ctype.h> +#include <getopt.h> +#include <syslog.h> +#include <unistd.h> + +#include "usb_modeswitch.h" + + +// Little helpers + +int usb_bulk_io(struct libusb_device_handle *handle, int ep, unsigned char *bytes, + int size, int timeout) +{ + int actual_length; + int r; +// usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); + r = libusb_bulk_transfer(handle, ep & 0xff, bytes, size, + &actual_length, timeout); + + /* if we timed out but did transfer some data, report as successful short + * read. FIXME: is this how libusb-0.1 works? */ + if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) + return actual_length; + + return r; +} + + +static int usb_interrupt_io(libusb_device_handle *handle, int ep, unsigned char *bytes, + int size, int timeout) +{ + int actual_length; + int r; +// usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout); + r = libusb_interrupt_transfer(handle, ep & 0xff, bytes, size, + &actual_length, timeout); + + /* if we timed out but did transfer some data, report as successful short + * read. FIXME: is this how libusb-0.1 works? */ + if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0)) + return actual_length; + + return (r); +} + + +#define LINE_DIM 1024 +#define MSG_DIM 11 +#define MAXLINES 50 +#define BUF_SIZE 4096 +#define DESCR_MAX 129 + +#define SEARCH_DEFAULT 0 +#define SEARCH_TARGET 1 +#define SEARCH_BUSDEV 2 + +#define SWITCH_CONFIG_MAXTRIES 5 + +#define SHOW_PROGRESS if (show_progress) fprintf + +char *TempPP=NULL; + +static struct libusb_context *ctx = NULL; +static struct libusb_device *dev = NULL; +static struct libusb_device_handle *devh = NULL; +static struct libusb_config_descriptor *active_config = NULL; + +int DefaultVendor=0, DefaultProduct=0, TargetVendor=0, TargetProduct=-1, TargetClass=0; +int MessageEndpoint=0, ResponseEndpoint=0, ReleaseDelay=0; +int targetDeviceCount=0, searchMode; +int devnum=-1, busnum=-1; + +unsigned int ModeMap = 0; +#define DETACHONLY_MODE 0x00000001 +#define HUAWEI_MODE 0x00000002 +#define SIERRA_MODE 0x00000004 +#define SONY_MODE 0x00000008 +#define GCT_MODE 0x00000010 +#define KOBIL_MODE 0x00000020 +#define SEQUANS_MODE 0x00000040 +#define MOBILEACTION_MODE 0x00000080 +#define CISCO_MODE 0x00000100 +#define QISDA_MODE 0x00000200 +#define QUANTA_MODE 0x00000400 +#define BLACKBERRY_MODE 0x00000800 +#define PANTECH_MODE 0x00001000 +#define HUAWEINEW_MODE 0x00002000 +#define OPTION_MODE 0x00004000 + + +int PantechMode=0; +char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0; +char NoDriverLoading=0, sysmode=0, mbim=0; +char StandardEject=0; + +char MessageContent[LINE_DIM]; +char MessageContent2[LINE_DIM]; +char MessageContent3[LINE_DIM]; +char TargetProductList[LINE_DIM]; +char DefaultProductList[5]; +unsigned char ByteString[LINE_DIM/2]; +unsigned char buffer[BUF_SIZE]; +char **Messages = NULL; + +FILE *output; + + +/* Settable Interface and Configuration (for debugging mostly) (jmw) */ +int Interface = -1, Configuration = 0, AltSetting = -1; + + +static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'e'}, + {"default-vendor", required_argument, 0, 'v'}, + {"default-product", required_argument, 0, 'p'}, + {"target-vendor", required_argument, 0, 'V'}, + {"target-product", required_argument, 0, 'P'}, + {"target-class", required_argument, 0, 'C'}, + {"message-endpoint", required_argument, 0, 'm'}, + {"message-content", required_argument, 0, 'M'}, + {"message-content2", required_argument, 0, '2'}, + {"message-content3", required_argument, 0, '3'}, + {"release-delay", required_argument, 0, 'w'}, + {"response-endpoint", required_argument, 0, 'r'}, + {"bus-num", required_argument, 0, 'b'}, + {"device-num", required_argument, 0, 'g'}, + {"detach-only", no_argument, 0, 'd'}, + {"huawei-mode", no_argument, 0, 'H'}, + {"huawei-new-mode", no_argument, 0, 'J'}, + {"sierra-mode", no_argument, 0, 'S'}, + {"sony-mode", no_argument, 0, 'O'}, + {"qisda-mode", no_argument, 0, 'B'}, + {"quanta-mode", no_argument, 0, 'E'}, + {"kobil-mode", no_argument, 0, 'T'}, + {"gct-mode", no_argument, 0, 'G'}, + {"sequans-mode", no_argument, 0, 'N'}, + {"mobileaction-mode", no_argument, 0, 'A'}, + {"cisco-mode", no_argument, 0, 'L'}, + {"blackberry-mode", no_argument, 0, 'Z'}, + {"option-mode", no_argument, 0, 'U'}, + {"pantech-mode", required_argument, 0, 'F'}, + {"std-eject", no_argument, 0, 'K'}, + {"need-response", no_argument, 0, 'n'}, + {"reset-usb", no_argument, 0, 'R'}, + {"config-file", required_argument, 0, 'c'}, + {"verbose", no_argument, 0, 'W'}, + {"quiet", no_argument, 0, 'Q'}, + {"sysmode", no_argument, 0, 'D'}, + {"inquire", no_argument, 0, 'I'}, + {"stdinput", no_argument, 0, 't'}, + {"find-mbim", no_argument, 0, 'j'}, + {"long-config", required_argument, 0, 'f'}, + {"check-success", required_argument, 0, 's'}, + {"interface", required_argument, 0, 'i'}, + {"configuration", required_argument, 0, 'u'}, + {"altsetting", required_argument, 0, 'a'}, + {0, 0, 0, 0} +}; + + +void readConfigFile(const char *configFilename) +{ + ParseParamHex(configFilename, TargetVendor); + ParseParamHex(configFilename, TargetProduct); + ParseParamString(configFilename, TargetProductList); + ParseParamHex(configFilename, TargetClass); + ParseParamHex(configFilename, DefaultVendor); + ParseParamHex(configFilename, DefaultProduct); + ParseParamBoolMap(configFilename, DetachStorageOnly, ModeMap, DETACHONLY_MODE); + ParseParamBoolMap(configFilename, HuaweiMode, ModeMap, HUAWEI_MODE); + ParseParamBoolMap(configFilename, HuaweiNewMode, ModeMap, HUAWEINEW_MODE); + ParseParamBoolMap(configFilename, SierraMode, ModeMap, SIERRA_MODE); + ParseParamBoolMap(configFilename, SonyMode, ModeMap, SONY_MODE); + ParseParamBoolMap(configFilename, GCTMode, ModeMap, GCT_MODE); + ParseParamBoolMap(configFilename, KobilMode, ModeMap, KOBIL_MODE); + ParseParamBoolMap(configFilename, SequansMode, ModeMap, SEQUANS_MODE); + ParseParamBoolMap(configFilename, MobileActionMode, ModeMap, MOBILEACTION_MODE); + ParseParamBoolMap(configFilename, CiscoMode, ModeMap, CISCO_MODE); + ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE); + ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE); + ParseParamBoolMap(configFilename, OptionMode, ModeMap, OPTION_MODE); + ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE); + ParseParamInt(configFilename, PantechMode); + if (PantechMode) + ModeMap |= PANTECH_MODE; + ParseParamBool(configFilename, StandardEject); + ParseParamBool(configFilename, NoDriverLoading); + ParseParamHex(configFilename, MessageEndpoint); + ParseParamString(configFilename, MessageContent); + ParseParamString(configFilename, MessageContent2); + ParseParamString(configFilename, MessageContent3); + ParseParamInt(configFilename, ReleaseDelay); + ParseParamHex(configFilename, ResponseEndpoint); + ParseParamHex(configFilename, ResetUSB); + ParseParamInt(configFilename, CheckSuccess); + ParseParamHex(configFilename, Interface); + ParseParamHex(configFilename, Configuration); + ParseParamHex(configFilename, AltSetting); + + /* TargetProductList has priority over TargetProduct */ + if (TargetProduct != -1 && TargetProductList[0] != '\0') { + TargetProduct = -1; + SHOW_PROGRESS(output,"Warning: TargetProductList overrides TargetProduct!\n"); + } + + config_read = 1; +} + + +void printConfig() +{ + if ( DefaultVendor ) + fprintf (output,"DefaultVendor= 0x%04x\n", DefaultVendor); + if ( DefaultProduct ) + fprintf (output,"DefaultProduct= 0x%04x\n", DefaultProduct); + if ( TargetVendor ) + fprintf (output,"TargetVendor= 0x%04x\n", TargetVendor); + if ( TargetProduct > -1 ) + fprintf (output,"TargetProduct= 0x%04x\n", TargetProduct); + if ( TargetClass ) + fprintf (output,"TargetClass= 0x%02x\n", TargetClass); + if ( strlen(TargetProductList) ) + fprintf (output,"TargetProductList=\"%s\"\n", TargetProductList); + if (StandardEject) + fprintf (output,"\nStandardEject=1\n"); + if (ModeMap & DETACHONLY_MODE) + fprintf (output,"\nDetachStorageOnly=1\n"); + if (ModeMap & HUAWEI_MODE) + fprintf (output,"HuaweiMode=1\n"); + if (ModeMap & HUAWEINEW_MODE) + fprintf (output,"HuaweiNewMode=1\n"); + if (ModeMap & SIERRA_MODE) + fprintf (output,"SierraMode=1\n"); + if (ModeMap & SONY_MODE) + fprintf (output,"SonyMode=1\n"); + if (ModeMap & QISDA_MODE) + fprintf (output,"QisdaMode=1\n"); + if (ModeMap & QUANTA_MODE) + fprintf (output,"QuantaMode=1\n"); + if (ModeMap & GCT_MODE) + fprintf (output,"GCTMode=1\n"); + if (ModeMap & KOBIL_MODE) + fprintf (output,"KobilMode=1\n"); + if (ModeMap & SEQUANS_MODE) + fprintf (output,"SequansMode=1\n"); + if (ModeMap & MOBILEACTION_MODE) + fprintf (output,"MobileActionMode=1\n"); + if (ModeMap & CISCO_MODE) + fprintf (output,"CiscoMode=1\n"); + if (ModeMap & BLACKBERRY_MODE) + fprintf (output,"BlackberryMode=1\n"); + if (ModeMap & OPTION_MODE) + fprintf (output,"OptionMode=1\n"); + if (ModeMap & PANTECH_MODE) + fprintf (output,"PantechMode=1\n"); + if ( MessageEndpoint ) + fprintf (output,"MessageEndpoint=0x%02x\n", MessageEndpoint); + if ( strlen(MessageContent) ) + fprintf (output,"MessageContent=\"%s\"\n", MessageContent); + if ( strlen(MessageContent2) ) + fprintf (output,"MessageContent2=\"%s\"\n", MessageContent2); + if ( strlen(MessageContent3) ) + fprintf (output,"MessageContent3=\"%s\"\n", MessageContent3); + if ( ResponseEndpoint ) + fprintf (output,"ResponseEndpoint=0x%02x\n", ResponseEndpoint); + if ( Interface > -1 ) + fprintf (output,"Interface=0x%02x\n", Interface); + if ( Configuration > 0 ) + fprintf (output,"Configuration=0x%02x\n", Configuration); + if ( AltSetting > -1 ) + fprintf (output,"AltSetting=0x%02x\n", AltSetting); + if ( CheckSuccess ) + fprintf (output,"Success check enabled, max. wait time %d seconds\n", CheckSuccess); + if ( sysmode ) + fprintf (output,"System integration mode enabled\n"); +} + + +int readArguments(int argc, char **argv) +{ + int c, option_index = 0, count=0; + char *longConfig = NULL; + if (argc==1) + { + printHelp(); + printVersion(); + exit(1); + } + + while (1) + { + c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZUF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:", + long_options, &option_index); + + /* Detect the end of the options. */ + if (c == -1) + break; + count++; + switch (c) + { + case 'R': ResetUSB = 1; break; + case 'v': DefaultVendor = strtol(optarg, NULL, 16); break; + case 'p': DefaultProduct = strtol(optarg, NULL, 16); break; + case 'V': TargetVendor = strtol(optarg, NULL, 16); break; + case 'P': TargetProduct = strtol(optarg, NULL, 16); break; + case 'C': TargetClass = strtol(optarg, NULL, 16); break; + case 'm': MessageEndpoint = strtol(optarg, NULL, 16); break; + case 'M': strncpy(MessageContent, optarg, LINE_DIM); break; + case '2': strncpy(MessageContent2, optarg, LINE_DIM); break; + case '3': strncpy(MessageContent3, optarg, LINE_DIM); break; + case 'w': ReleaseDelay = strtol(optarg, NULL, 10); break; + case 'n': break; + case 'r': ResponseEndpoint = strtol(optarg, NULL, 16); break; + case 'K': StandardEject = 1; break; + case 'd': ModeMap = ModeMap + DETACHONLY_MODE; break; + case 'H': ModeMap = ModeMap + HUAWEI_MODE; break; + case 'J': ModeMap = ModeMap + HUAWEINEW_MODE; break; + case 'S': ModeMap = ModeMap + SIERRA_MODE; break; + case 'O': ModeMap = ModeMap + SONY_MODE; break;; break; + case 'B': ModeMap = ModeMap + QISDA_MODE; break; + case 'E': ModeMap = ModeMap + QUANTA_MODE; break; + case 'G': ModeMap = ModeMap + GCT_MODE; break; + case 'T': ModeMap = ModeMap + KOBIL_MODE; break; + case 'N': ModeMap = ModeMap + SEQUANS_MODE; break; + case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break; + case 'L': ModeMap = ModeMap + CISCO_MODE; break; + case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break; + case 'U': ModeMap = ModeMap + OPTION_MODE; break; + case 'F': ModeMap = ModeMap + PANTECH_MODE; + PantechMode = strtol(optarg, NULL, 10); break; + case 'c': readConfigFile(optarg); break; + case 't': readConfigFile("stdin"); break; + case 'W': verbose = 1; show_progress = 1; count--; break; + case 'Q': show_progress = 0; verbose = 0; count--; break; + case 'D': sysmode = 1; count--; break; + case 's': CheckSuccess = strtol(optarg, NULL, 10); count--; break; + case 'I': break; + case 'b': busnum = strtol(optarg, NULL, 10); break; + case 'g': devnum = strtol(optarg, NULL, 10); break; + + case 'i': Interface = strtol(optarg, NULL, 16); break; + case 'u': Configuration = strtol(optarg, NULL, 16); break; + case 'a': AltSetting = strtol(optarg, NULL, 16); break; + case 'j': mbim = 1; break; + + case 'f': + longConfig = malloc(strlen(optarg)+5); + strcpy(longConfig,"##\n"); + strcat(longConfig,optarg); + strcat(longConfig,"\n"); + readConfigFile(longConfig); + free(longConfig); + break; + + case 'e': + printVersion(); + exit(0); + break; + case 'h': + printVersion(); + printHelp(); + exit(0); + break; + + default: /* Unsupported - error message has already been printed */ + fprintf (output,"\n"); + printHelp(); + exit(1); + } + } + return count; +} + + +int main(int argc, char **argv) +{ + int ret=0, numDefaults=0, sonySuccess=0, i; + int currentConfigVal=0, defaultClass=0, interfaceClass=0; + struct libusb_device_descriptor descriptor; + enum libusb_error libusbError; + + /* Make sure we have empty strings even if not set by config */ + TargetProductList[0] = '\0'; + MessageContent[0] = '\0'; + MessageContent2[0] = '\0'; + MessageContent3[0] = '\0'; + DefaultProductList[0] = '\0'; + + /* Useful for debugging during boot */ +// output=fopen("/dev/console", "w"); + output=stdout; + + signal(SIGTERM, release_usb_device); + + /* + * Parameter parsing, USB preparation/diagnosis, plausibility checks + */ + + /* Check command arguments, use params instead of config file when given */ + switch (readArguments(argc, argv)) { + case 0: /* no argument or -W, -q or -s */ + break; + default: /* one or more arguments except -W, -q or -s */ + if (!config_read) /* if arguments contain -c, the config file was already processed */ + if (verbose) fprintf(output,"Take all parameters from the command line\n\n"); + } + + if (verbose) { + printVersion(); + printConfig(); + fprintf(output,"\n"); + } + + /* Some sanity checks. The default IDs are mandatory */ + if (!(DefaultVendor && DefaultProduct)) { + SHOW_PROGRESS(output,"No default vendor/product ID given. Abort\n\n"); + exit(1); + } + + if (strlen(MessageContent)) { + if (strlen(MessageContent) % 2 != 0) { + fprintf(stderr, "Error: MessageContent hex string has uneven length. Abort\n\n"); + exit(1); + } + if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) { + fprintf(stderr, "Error: MessageContent %s\n is not a hex string. Abort\n\n", + MessageContent); + + exit(1); + } + } + + if (devnum == -1) { + searchMode = SEARCH_DEFAULT; + } else { + SHOW_PROGRESS(output,"Use given bus/device number: %03d/%03d ...\n", busnum, devnum); + searchMode = SEARCH_BUSDEV; + } + + if (show_progress) + if (CheckSuccess && !(TargetVendor || TargetProduct > -1 || TargetProductList[0] != '\0') + && !TargetClass) + + fprintf(output,"Note: No target parameter given; success check limited\n"); + + if (TargetProduct > -1 && TargetProductList[0] == '\0') { + sprintf(TargetProductList,"%04x",TargetProduct); + TargetProduct = -1; + } + + /* libusb initialization */ + if ((libusbError = libusb_init(&ctx)) != LIBUSB_SUCCESS) { + //fprintf(stderr, "Error: Failed to initialize libusb. %s (%d)\n\n", + //libusb_error_name(libusbError), libusbError); + exit(1); + } + + if (verbose) + libusb_set_debug(ctx, 3); + + if (mbim) { + printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) ); + exit(0); + } + + /* Count existing target devices, remember for success check */ + if (searchMode != SEARCH_BUSDEV && (TargetVendor || TargetClass)) { + SHOW_PROGRESS(output,"Look for target devices ...\n"); + search_devices(&targetDeviceCount, TargetVendor, TargetProductList, TargetClass, 0, + SEARCH_TARGET); + + if (targetDeviceCount) { + SHOW_PROGRESS(output," Found devices in target mode or class (%d)\n", targetDeviceCount); + } else + SHOW_PROGRESS(output," No devices in target mode or class found\n"); + } + + /* Count default devices, get the last one found */ + SHOW_PROGRESS(output,"Look for default devices ...\n"); + + sprintf(DefaultProductList,"%04x",DefaultProduct); + dev = search_devices(&numDefaults, DefaultVendor, DefaultProductList, TargetClass, + Configuration, searchMode); + + if (numDefaults) { + SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults); + } else { + SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n"); + close_all(); + exit(0); + } + + if (dev == NULL) { + SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n"); + close_all(); + exit(0); + } else { + if (devnum == -1) { + devnum = libusb_get_device_address(dev); + busnum = libusb_get_bus_number(dev); + SHOW_PROGRESS(output,"Access device %03d on bus %03d\n", devnum, busnum); + } + libusb_open(dev, &devh); + if (devh == NULL) { + SHOW_PROGRESS(output,"Error opening the device. Abort\n\n"); + abortExit(); + } + } + + /* Get current configuration of default device, note value if Configuration + * parameter is set. Also sets active_config + */ + currentConfigVal = get_current_config_value(dev); + if (Configuration > -1) { + SHOW_PROGRESS(output,"Current configuration number is %d\n", currentConfigVal); + } else + currentConfigVal = 0; + + libusb_get_device_descriptor(dev, &descriptor); + defaultClass = descriptor.bDeviceClass; + if (Interface == -1) + Interface = active_config->interface[0].altsetting[0].bInterfaceNumber; + SHOW_PROGRESS(output,"Use interface number %d\n", Interface); + + /* Get class of default device/interface */ + interfaceClass = get_interface_class(); + + /* Check or get endpoints and alloc message list if needed*/ + if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE + || ModeMap & HUAWEINEW_MODE || ModeMap & OPTION_MODE) { + + Messages = (char**) calloc(MSG_DIM, sizeof(char*)); + for (i = 0; i < MSG_DIM; i++) { + Messages[i] = (char*) calloc(LINE_DIM, sizeof(char)); + Messages[i][0] = '\0'; + } + + if (!MessageEndpoint) + MessageEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT); + if (!ResponseEndpoint) + ResponseEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN); + if (!MessageEndpoint) { + fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n"); + abortExit(); + } + if (!ResponseEndpoint) { + fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n"); + abortExit(); + } + SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint, + ResponseEndpoint); + + } + + if (interfaceClass == -1) { + fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface); + abortExit(); + } + + if (defaultClass == 0 || defaultClass == 0xef) + defaultClass = interfaceClass; + else + if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE + && defaultClass != LIBUSB_CLASS_VENDOR_SPEC) { + + /* Unexpected default class combined with differing interface class */ + SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass); + defaultClass = 8; + } + + if (strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0) + if (defaultClass != 8) { + fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n" + " interface class is %d, expected 8. Abort\n\n", Interface, defaultClass); + abortExit(); + } + + if (show_progress) { + fprintf(output,"\nUSB description data (for identification)\n"); + deviceDescription(); + } + + /* Special modes are exclusive, so check for illegal combinations. + * More than one bit set? + */ + if ( ModeMap & (ModeMap-1) ) { + fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n"); + abortExit(); + } + + if ((strlen(MessageContent) || StandardEject) && ModeMap ) { + MessageContent[0] = '\0'; + StandardEject = 0; + fprintf(output,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n"); + } + + if (StandardEject && (strlen(MessageContent2) || strlen(MessageContent3))) { + fprintf(output,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n"); + } + + if ( !ModeMap && !strlen(MessageContent) && AltSetting == -1 && !Configuration && !StandardEject ) + SHOW_PROGRESS(output,"Warning: no switching method given. See documentation\n"); + + /* + * The switching actions + */ + + if (sysmode) { + openlog("usb_modeswitch", 0, LOG_SYSLOG); + syslog(LOG_NOTICE, "switch device %04x:%04x on %03d/%03d", DefaultVendor, DefaultProduct, + busnum, devnum); + + } + + if (ModeMap & DETACHONLY_MODE) { + SHOW_PROGRESS(output,"Detach storage driver as switching method ...\n"); + ret = detachDriver(); + if (ret == 2) + SHOW_PROGRESS(output," You may want to remove the storage driver manually\n"); + } + + if(ModeMap & HUAWEI_MODE) { + switchHuaweiMode(); + } + if(ModeMap & SIERRA_MODE) { + switchSierraMode(); + } + if(ModeMap & GCT_MODE) { + detachDriver(); + switchGCTMode(); + } + if(ModeMap & QISDA_MODE) { + switchQisdaMode(); + } + if(ModeMap & KOBIL_MODE) { + detachDriver(); + switchKobilMode(); + } + if(ModeMap & QUANTA_MODE) { + switchQuantaMode(); + } + if(ModeMap & SEQUANS_MODE) { + switchSequansMode(); + } + if(ModeMap & MOBILEACTION_MODE) { + switchActionMode(); + } + if(ModeMap & CISCO_MODE) { + detachDriver(); + switchCiscoMode(); + } + if(ModeMap & BLACKBERRY_MODE) { + detachDriver(); + switchBlackberryMode(); + } + if(ModeMap & PANTECH_MODE) { + detachDriver(); + if (PantechMode > 1) + switchPantechMode(); + else + SHOW_PROGRESS(output,"Waiting for auto-switch of Pantech modem ...\n"); + } + if(ModeMap & SONY_MODE) { + if (CheckSuccess) + SHOW_PROGRESS(output,"Note: CheckSuccess ignored; Sony mode does separate checks\n"); + CheckSuccess = 0; /* separate and implied success control */ + sonySuccess = switchSonyMode(); + } + + if (StandardEject) { + SHOW_PROGRESS(output,"Sending standard EJECT sequence\n"); + detachDriver(); + + strcpy(Messages[0],"5553424387654321000000000000061e000000000000000000000000000000"); + strcpy(Messages[1],"5553424397654321000000000000061b000000020000000000000000000000"); + strcpy(Messages[2],"5553424387654321000000000001061e000000000000000000000000000000"); + strcpy(Messages[3],"5553424397654321000000000001061b000000020000000000000000000000"); + if (MessageContent[0] != '\0') + strcpy(Messages[4], MessageContent); + + switchSendMessage(); + } else if (ModeMap & HUAWEINEW_MODE) { + SHOW_PROGRESS(output,"Using standard Huawei switching message\n"); + detachDriver(); + strcpy(Messages[0],"55534243123456780000000000000011062000000101000100000000000000"); + switchSendMessage(); + } else if (ModeMap & OPTION_MODE) { + SHOW_PROGRESS(output,"Using standard Option switching message\n"); + detachDriver(); +// strcpy(MessageContent,"55534243123456780100000080000601000000000000000000000000000000"); + strcpy(Messages[0],"55534243123456780000000000000601000000000000000000000000000000"); + switchSendMessage(); + } else if (strlen(MessageContent)) { + detachDriver(); + strcpy(Messages[0],MessageContent); + switchSendMessage(); + } + + if (Configuration > 0) { + if (currentConfigVal != Configuration) { + if (switchConfiguration()) { + currentConfigVal = get_current_config_value(dev); + if (currentConfigVal == Configuration) { + SHOW_PROGRESS(output,"The configuration was set successfully\n"); + } else { + SHOW_PROGRESS(output,"Changing the configuration has failed\n"); + } + } + } else { + SHOW_PROGRESS(output,"Target configuration %d found. Do nothing\n", currentConfigVal); + } + } + + if (AltSetting != -1) { + switchAltSetting(); + } + + /* No "removal" check if these are set */ + if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) { + libusb_close(devh); + devh = NULL; + } + + if (ResetUSB) { + resetUSB(); + devh = NULL; + } + + if (searchMode == SEARCH_BUSDEV && sysmode) { + printf("ok:busdev\n"); + close_all(); + exit(0); + } + + if (CheckSuccess) { + if (checkSuccess()) { + if (sysmode) { + if (NoDriverLoading) + printf("ok:\n"); + else + if (TargetProduct < 1) + printf("ok:no_data\n"); + else + printf("ok:%04x:%04x\n", TargetVendor, TargetProduct); + } + } else + if (sysmode) + printf("fail:\n"); + } else { + if (ModeMap & SONY_MODE) + if (sonySuccess) { + if (sysmode) { + syslog(LOG_NOTICE, "switched S.E. MD400 to modem mode"); + printf("ok:\n"); /* ACM device, no driver action */ + } + SHOW_PROGRESS(output,"-> device should be stable now. Bye!\n\n"); + } else { + if (sysmode) + printf("fail:\n"); + SHOW_PROGRESS(output,"-> switching was probably not completed. Bye!\n\n"); + } + else + SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n"); + } + close_all(); + exit(0); +} + + +/* Get descriptor strings if available (identification details) */ +void deviceDescription () +{ + char imanufact[DESCR_MAX], iproduct[DESCR_MAX], iserial[DESCR_MAX]; + int ret=0; + char* c; + memset (imanufact, ' ', DESCR_MAX); + memset (iproduct, ' ', DESCR_MAX); + memset (iserial, ' ', DESCR_MAX); + + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + int iManufacturer = descriptor.iManufacturer; + int iProduct = descriptor.iProduct; + int iSerialNumber = descriptor.iSerialNumber; + + if (iManufacturer) { + ret = libusb_get_string_descriptor_ascii(devh, iManufacturer, (unsigned char *)imanufact, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"manufacturer\"\n"); + strcpy(imanufact, "read error"); + } + } else + strcpy(imanufact, "not provided"); + c = strstr(imanufact, " "); + if (c) + memset((void*)c, '\0', 1); + + if (iProduct) { + ret = libusb_get_string_descriptor_ascii(devh, iProduct, (unsigned char *)iproduct, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"product\"\n"); + strcpy(iproduct, "read error"); + } + } else + strcpy(iproduct, "not provided"); + c = strstr(iproduct, " "); + if (c) + memset((void*)c, '\0', 1); + + if (iSerialNumber) { + ret = libusb_get_string_descriptor_ascii(devh, iSerialNumber, (unsigned char *)iserial, DESCR_MAX); + if (ret < 0) { + fprintf(stderr, "Error: could not get description string \"serial number\"\n"); + strcpy(iserial, "read error"); + } + } else + strcpy(iserial, "not provided"); + c = strstr(iserial, " "); + if (c) + memset((void*)c, '\0', 1); + fprintf(output,"-------------------------\n"); + fprintf(output,"Manufacturer: %s\n", imanufact); + fprintf(output," Product: %s\n", iproduct); + fprintf(output," Serial No.: %s\n", iserial); + fprintf(output,"-------------------------\n"); +} + + +/* Auxiliary function used by the wrapper */ +int findMBIMConfig(int vendor, int product, int mode) +{ + struct libusb_device **devs; + int resultConfig=0; + int i=0, j; + + if (libusb_get_device_list(ctx, &devs) < 0) { + perror("Libusb could not access USB. Abort"); + return 0; + } + + SHOW_PROGRESS(output,"Search USB devices ...\n"); + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + if (mode == SEARCH_BUSDEV) { + if ((libusb_get_bus_number(dev) != busnum) || + (libusb_get_device_address(dev) != devnum)) { + continue; + } else { + if (descriptor.idVendor != vendor) + continue; + if (product != descriptor.idProduct) + continue; + } + } + SHOW_PROGRESS(output,"Found device, search for MBIM configuration...\n"); + + // No check if there is only one configuration + if (descriptor.bNumConfigurations < 2) + return -1; + + // Checking all interfaces of all configurations + for (j=0; j<descriptor.bNumConfigurations; j++) { + struct libusb_config_descriptor *config; + + libusb_get_config_descriptor(dev, j, &config); + resultConfig = config->bConfigurationValue; + for (i=0; i<config->bNumInterfaces; i++) { + if ( config->interface[i].altsetting[0].bInterfaceClass == 2 ) + if ( config->interface[i].altsetting[0].bInterfaceSubClass == 0x0e ) { + // found MBIM interface in this configuration + libusb_free_config_descriptor(config); + return resultConfig; + } + } + libusb_free_config_descriptor(config); + } + return -1; + } + return 0; +} + + +void resetUSB () +{ + int success; + int bpoint = 0; + + if (!devh) { + fprintf(output,"Device handle empty, skip USB reset\n"); + return; + } + if (show_progress) { + fprintf(output,"Reset USB device "); + fflush(output); + } + sleep( 1 ); + do { + success = libusb_reset_device(devh); + if ( ((bpoint % 10) == 0) && show_progress ) { + fprintf(output,"."); + fflush(output); + } + bpoint++; + if (bpoint > 100) + success = 1; + } while (success < 0); + + if ( success ) { + SHOW_PROGRESS(output,"\n Device reset failed.\n"); + } else + SHOW_PROGRESS(output,"\n Device was reset\n"); +} + + +int switchSendMessage () +{ + const char* cmdHead = "55534243"; + int ret, i; +/* char* msg[3]; + msg[0] = MessageContent; + msg[1] = MessageContent2; + msg[2] = MessageContent3; +*/ + SHOW_PROGRESS(output,"Set up interface %d\n", Interface); + ret = libusb_claim_interface(devh, Interface); + if (ret != 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret); + return 0; + } + libusb_clear_halt(devh, MessageEndpoint); + SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint); + if (show_progress) + fflush(stdout); + + for (i=0; i<MSG_DIM; i++) { + if ( strlen(Messages[i]) == 0) + break; + + if ( sendMessage(Messages[i], i+1) ) + goto skip; + + if ( strstr(Messages[i],cmdHead) != NULL ) { + // UFI command + SHOW_PROGRESS(output,"Read the response to message %d (CSW) ...\n", i+1); + ret = read_bulk(ResponseEndpoint, ByteString, 13); + if (ret >= 0) + SHOW_PROGRESS(output,", status %d",ByteString[12]); + } else { + // Other bulk transfer + SHOW_PROGRESS(output,"Read the response to message %d ...\n", i+1); + ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 ); + } + SHOW_PROGRESS(output,"\n"); + if (ret < 0) + goto skip; + } + + SHOW_PROGRESS(output,"Reset response endpoint 0x%02x\n", ResponseEndpoint); + ret = libusb_clear_halt(devh, ResponseEndpoint); + if (ret) + SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret); + SHOW_PROGRESS(output,"Reset message endpoint 0x%02x\n", MessageEndpoint); + ret = libusb_clear_halt(devh, MessageEndpoint); + if (ret) + SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret); + usleep(50000); + + if (ReleaseDelay) { + SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay); + usleep(ReleaseDelay*1000); + } + ret = libusb_release_interface(devh, Interface); + if (ret) + goto skip; + return 1; + +skip: + SHOW_PROGRESS(output," Device is gone, skip any further commands\n"); + libusb_close(devh); + devh = NULL; + return 2; +} + + +int switchConfiguration () +{ + int ret, count = SWITCH_CONFIG_MAXTRIES; + + SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration); + while (((ret = libusb_set_configuration(devh, Configuration)) < 0) && --count) { + SHOW_PROGRESS(output," Device is busy, try to detach kernel driver\n"); + detachDriver(); + } + if (ret < 0 ) { + SHOW_PROGRESS(output," Changing the configuration failed (error %d). Try to continue\n", ret); + return 0; + } else { + SHOW_PROGRESS(output," OK, configuration set\n"); + return 1; + } +} + + +int switchAltSetting () +{ + int ret; + SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting); + ret = libusb_claim_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip AltSetting\n", ret); + return 0; + } + ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting); + libusb_release_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Change to alt setting returned error %d. Try to continue\n", ret); + return 0; + } else + return 1; +} + + +void switchHuaweiMode () +{ + int ret; + SHOW_PROGRESS(output,"Send old Huawei control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, buffer, 0, 1000); + + if (ret != 0) { + fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchSierraMode () +{ + int ret; + SHOW_PROGRESS(output,"Send Sierra control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + LIBUSB_REQUEST_SET_INTERFACE, 00000001, 0, buffer, 0, 1000); + if (ret == LIBUSB_ERROR_PIPE) { + SHOW_PROGRESS(output," communication with device stopped. May have switched modes anyway\n"); + return; + } + if (ret < 0) { + fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchGCTMode () +{ + int ret; + ret = libusb_claim_interface(devh, Interface); + if (ret != 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret); + return; + } + SHOW_PROGRESS(output,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d", + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN); + + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, + 0xa0, 0, Interface, buffer, 1, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," GCT control message 1 failed (error %d), continue anyway ...\n", ret); + } + SHOW_PROGRESS(output,"Send GCT control message 2 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, + 0xfe, 0, Interface, buffer, 1, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," GCT control message 2 failed (error %d). Abort\n\n", ret); + } + libusb_release_interface(devh, Interface); + if (ret < 0) + exit(0); +} + + +void switchKobilMode() { + int ret; + SHOW_PROGRESS(output,"Send Kobil control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0x88, 0, 0, buffer, 8, 1000); + + if (ret < 0) { + fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchQisdaMode () { + int ret; + SHOW_PROGRESS(output,"Sending Qisda control message ...\n"); + memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16); + ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, buffer, 16, 1000); + if (ret < 0) { + fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchQuantaMode() { + int ret; + SHOW_PROGRESS(output,"Send Quanta control message ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xff, 0, 0, buffer, 0, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchBlackberryMode () +{ + int ret; + SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xb1, 0x0000, 0, buffer, 8, 1000); + + if (ret != 8) { + fprintf(stderr, "Error: Blackberry control message 1 failed (result %d)\n", ret); + } + SHOW_PROGRESS(output,"Send Blackberry control message 2 ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, + 0xa9, 0x000e, 0, buffer, 2, 1000); + + if (ret != 2) { + fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchPantechMode() +{ + int ret; + SHOW_PROGRESS(output,"Send Pantech control message, wValue %d ...\n", PantechMode); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, + 0x70, PantechMode, 0, buffer, 0, 1000); + + if (ret < 0) { + SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +#define EP_OUT 0x02 +#define EP_IN 0x81 +#define SIZE 0x08 + +#define MOBILE_ACTION_READLOOP1 63 +#define MOBILE_ACTION_READLOOP2 73 + +/* The code here is statically derived from sniffing (and confirmed working). + * However I bet it could be simplified significantly. + */ + +void switchActionMode () +{ + int ret, i; + SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n"); + memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE); + libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + 0x09, 0x0300, 0, buffer, SIZE, 1000); + + memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE); + libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + 0x09, 0x0300, 0, buffer, SIZE, 1000); + + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + for (i=0; i < MOBILE_ACTION_READLOOP1; i++) { + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + } + memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + for (i=0; i < MOBILE_ACTION_READLOOP2; i++) { + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + } + memcpy(buffer, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE); + usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + memcpy(buffer, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE); + ret = usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000); + usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000); + if (ret < 0) { + SHOW_PROGRESS(output," MobileAction control sequence did not complete\n" + " Last error was %d\n",ret); + } else { + SHOW_PROGRESS(output," MobileAction control sequence complete\n"); + } +} + + +#define SQN_SET_DEVICE_MODE_REQUEST 0x0b +#define SQN_GET_DEVICE_MODE_REQUEST 0x0a + +#define SQN_DEFAULT_DEVICE_MODE 0x00 +#define SQN_MASS_STORAGE_MODE 0x01 +#define SQN_CUSTOM_DEVICE_MODE 0x02 + +void switchSequansMode() +{ + + int ret; + SHOW_PROGRESS(output,"Send Sequans control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_OUT, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE, + 0, buffer, 0, 1000); + + if (ret < 0) { + fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret); + exit(0); + } +} + + +void switchCiscoMode() +{ + int ret, i, j; + + strcpy(Messages[0],"55534243f83bcd810002000080000afd000000030000000100000000000000"); + strcpy(Messages[1],"55534243984300820002000080000afd000000070000000100000000000000"); + strcpy(Messages[2],"55534243984300820000000000000afd000100071000000000000000000000"); + strcpy(Messages[3],"55534243984300820002000080000afd000200230000000100000000000000"); + strcpy(Messages[4],"55534243984300820000000000000afd000300238200000000000000000000"); + strcpy(Messages[5],"55534243984300820002000080000afd000200260000000100000000000000"); + strcpy(Messages[6],"55534243984300820000000000000afd00030026c800000000000000000000"); + strcpy(Messages[7],"55534243d84c04820002000080000afd000010730000000100000000000000"); + strcpy(Messages[8],"55534243d84c04820002000080000afd000200240000000100000000000000"); + strcpy(Messages[9],"55534243d84c04820000000000000afd000300241300000000000000000000"); + strcpy(Messages[10],"55534243d84c04820000000000000afd000110732400000000000000000000"); + + SHOW_PROGRESS(output,"Set up Cisco interface %d\n", Interface); + ret = libusb_claim_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret); + abortExit(); + } +// libusb_clear_halt(devh, MessageEndpoint); + if (show_progress) + fflush(output); + +// ret = read_bulk(ResponseEndpoint, ByteString, 13); +// SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret); + + for (i=0; i<11; i++) { + if ( sendMessage(Messages[i], i+1) ) + goto skip; + + for (j=1; j<4; j++) { + + SHOW_PROGRESS(output," Read the CSW for bulk message %d (attempt %d) ...\n",i+1,j); + ret = read_bulk(ResponseEndpoint, ByteString, 13); + SHOW_PROGRESS(output,"\n"); + + if (ret < 0) + goto skip; + if (ret == 13) + break; + } + } + libusb_clear_halt(devh, MessageEndpoint); + libusb_clear_halt(devh, ResponseEndpoint); + + ReleaseDelay = 2000; + SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay); + usleep(ReleaseDelay*1000); + + ret = libusb_release_interface(devh, Interface); + if (ret < 0) + goto skip; + return; + +skip: + SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret); + libusb_close(devh); + devh = NULL; +} + + +int switchSonyMode () +{ + int ret, i, found; + detachDriver(); + + if (CheckSuccess) { + CheckSuccess = 0; + } + + SHOW_PROGRESS(output,"Send Sony control message\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100); + + if (ret < 0) { + fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret); + exit(0); + } else + SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n"); + + libusb_close(devh); + devh = NULL; + + /* Now waiting for the device to reappear */ + devnum=-1; + busnum=-1; + i=0; + dev = 0; + while ( dev == 0 && i < 30 ) { + if ( i > 5 ) { + dev = search_devices(&found, DefaultVendor, DefaultProductList, TargetClass, + 0, SEARCH_TARGET); + } + if ( dev != 0 ) + break; + sleep(1); + if (show_progress) { + fprintf(output,"#"); + fflush(stdout); + } + i++; + } + SHOW_PROGRESS(output,"\n After %d seconds:",i); + if ( dev ) { + SHOW_PROGRESS(output," device came back, proceed\n"); + libusb_open(dev, &devh); + if (devh == 0) { + fprintf(stderr, "Error: could not get handle on device\n"); + return 0; + } + } else { + SHOW_PROGRESS(output," device still gone, abort\n"); + return 0; + } + sleep(1); + + SHOW_PROGRESS(output,"Send Sony control message again ...\n"); + ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE + | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100); + + if (ret < 0) { + fprintf(stderr, "Error: Sony control message (2) failed (error %d)\n", ret); + return 0; + } + SHOW_PROGRESS(output," OK, control message sent\n"); + return 1; +} + + +/* Detach driver + */ +int detachDriver() +{ + + int ret; + SHOW_PROGRESS(output,"Looking for active driver ...\n"); + ret = libusb_kernel_driver_active(devh, 0); + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) { + fprintf(output," Can't do driver detection on this platform.\n"); + return 2; + } + if (ret < 0) { + fprintf(output," Driver check failed with error %d. Try to continue\n", ret); + return 2; + } + if (ret == 0) { + SHOW_PROGRESS(output," No active driver found. Detached before or never attached\n"); + return 1; + } + + ret = libusb_detach_kernel_driver(devh, Interface); + if (ret == LIBUSB_ERROR_NOT_SUPPORTED) { + fprintf(output," Can't do driver detaching on this platform.\n"); + return 2; + } + if (ret == 0) { + SHOW_PROGRESS(output," OK, driver detached\n"); + } else + SHOW_PROGRESS(output," Driver detach failed (error %d). Try to continue\n", ret); + return 1; +} + + +int sendMessage(char* message, int count) +{ + int ret, message_length; + + if (strlen(message) % 2 != 0) { + fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count); + return 1; + } + message_length = strlen(message) / 2; + if ( hexstr2bin(message, ByteString, message_length) == -1) { + fprintf(stderr, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", + count, MessageContent); + + return 1; + } + SHOW_PROGRESS(output,"Trying to send message %d to endpoint 0x%02x ...\n", count, MessageEndpoint); + fflush(output); + ret = write_bulk(MessageEndpoint, ByteString, message_length); + if (ret == LIBUSB_ERROR_NO_DEVICE) + return 1; + + return 0; +} + + +int checkSuccess() +{ + int ret, i; + int newTargetCount, success=0; + + SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess); + sleep(1); + + /* If target parameters are given, don't check for vanished device + * Changed for Cisco AM10 where a new device is added while the install + * storage device stays active + */ + if ((TargetVendor || TargetClass) && devh) { + libusb_close(devh); + devh = NULL; + } + + /* if target ID is not given but target class is, assign default as target; + * it will be needed for sysmode output + */ + if (!TargetVendor && TargetClass) { + TargetVendor = DefaultVendor; + TargetProduct = DefaultProduct; + } + + /* devh is 0 if device vanished during command transmission or if target params were given + */ + if (devh) + for (i=0; i < CheckSuccess; i++) { + + /* Test if default device still can be accessed; positive result does + * not necessarily mean failure + */ + SHOW_PROGRESS(output," Wait for original device to vanish ...\n"); + + ret = libusb_claim_interface(devh, Interface); + libusb_release_interface(devh, Interface); + if (ret < 0) { + SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n"); + libusb_close(devh); + devh = NULL; + break; + } + if (i == CheckSuccess-1) { + SHOW_PROGRESS(output," Original device still present after the timeout\n\n" + "Mode switch most likely failed. Bye!\n\n"); + } else + sleep(1); + } + + if ( TargetVendor && (TargetProduct > -1 || TargetProductList[0] != '\0') ) { + + /* Recount target devices (compare with previous count) if target data is given. + * Target device on the same bus with higher device number is returned, + * description is read for syslog message + */ + for (i=i; i < CheckSuccess; i++) { + SHOW_PROGRESS(output," Search for target devices ...\n"); + dev = search_devices(&newTargetCount, TargetVendor, TargetProductList, + TargetClass, 0, SEARCH_TARGET); + + if (dev && (newTargetCount > targetDeviceCount)) { + if (verbose) { + libusb_open(dev, &devh); + fprintf(output,"\nFound target device %03d on bus %03d\n", + libusb_get_device_address(dev), libusb_get_bus_number(dev)); + + fprintf(output,"\nTarget device description data\n"); + deviceDescription(); + libusb_close(devh); + devh = NULL; + } + SHOW_PROGRESS(output," Found correct target device\n\n" + "Mode switch succeeded. Bye!\n\n"); + + success = 2; + break; + } + if (i == CheckSuccess-1) { + SHOW_PROGRESS(output," No new devices in target mode or class found\n\n" + "Mode switch has failed. Bye!\n\n"); + } else + sleep(1); + } + } else + /* No target data given, rely on the vanished device */ + if (!devh) { + SHOW_PROGRESS(output," (For a better success check provide target IDs or class)\n"); + SHOW_PROGRESS(output," Original device vanished after switching\n\n" + "Mode switch most likely succeeded. Bye!\n\n"); + success = 1; + } + + switch (success) { + case 3: + if (sysmode) + syslog(LOG_NOTICE, "switched to new device, but hit libusb1 bug"); + TargetProduct = -1; + success = 1; + break; + case 2: + if (sysmode) + syslog(LOG_NOTICE, "switched to %04x:%04x on %03d/%03d", TargetVendor, + TargetProduct, busnum, devnum); + + success = 1; + break; + case 1: + if (sysmode) + syslog(LOG_NOTICE, "device seems to have switched"); + default: + ; + } + if (sysmode) + closelog(); + + return success; + +} + + +int write_bulk(int endpoint, unsigned char *message, int length) +{ + int ret = usb_bulk_io(devh, endpoint, message, length, 3000); + if (ret >= 0 ) { + SHOW_PROGRESS(output," OK, message successfully sent\n"); + } else + if (ret == LIBUSB_ERROR_NO_DEVICE) { + SHOW_PROGRESS(output," Device seems to have vanished right after sending. Good.\n"); + } else + SHOW_PROGRESS(output," Sending the message returned error %d. Try to continue\n", ret); + return ret; + +} + + +int read_bulk(int endpoint, unsigned char *buffer, int length) +{ + int ret = usb_bulk_io(devh, endpoint, buffer, length, 3000); + if (ret >= 0 ) { + SHOW_PROGRESS(output," Response successfully read (%d bytes)", ret); + } else + if (ret == LIBUSB_ERROR_NO_DEVICE) { + SHOW_PROGRESS(output," Device seems to have vanished after reading. Good."); + } else + SHOW_PROGRESS(output," Response reading failed (error %d)", ret); + return ret; + +} + + +void release_usb_device(int __attribute__((unused)) dummy) +{ + SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n"); + if (devh) + libusb_release_interface(devh, Interface); + close_all(); + exit(0); + +} + + +/* Iterates over busses and devices, counts the ones which match the given + * parameters and returns the last one of them +*/ +struct libusb_device* search_devices( int *numFound, int vendor, char* productList, + int targetClass, int configuration, int mode) +{ + char *listcopy=NULL, *token; + unsigned char buffer[2]; + int devClass, product; + struct libusb_device* right_dev = NULL; +// struct libusb_device_handle *testdevh; + struct libusb_device **devs; + int i=0; + + /* only target class given, target vendor and product assumed unchanged */ + if ( targetClass && !(vendor || strlen(productList)) ) { + vendor = DefaultVendor; + productList = DefaultProductList; + } + *numFound = 0; + + /* Sanity check */ + if (!vendor || productList == '\0') + return NULL; + + listcopy = malloc(strlen(productList)+1); + + if (libusb_get_device_list(ctx, &devs) < 0) { + perror("Libusb failed to get USB access!"); + return 0; + } + + while ((dev = devs[i++]) != NULL) { + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + + if (mode == SEARCH_BUSDEV) { + if ((libusb_get_bus_number(dev) != busnum) || + (libusb_get_device_address(dev) != devnum)) + continue; + else + SHOW_PROGRESS(output," bus/device number matched\n"); + } + + if (verbose) + fprintf (output," found USB ID %04x:%04x\n", + descriptor.idVendor, descriptor.idProduct); + if (descriptor.idVendor != vendor) + continue; + if (verbose) + fprintf (output," vendor ID matched\n"); + + strcpy(listcopy, productList); + token = strtok(listcopy, ","); + while (token != NULL) { + if (strlen(token) != 4) { + SHOW_PROGRESS(output,"Error: entry in product ID list has wrong length: %s. " + "Ignored\n", token); + + goto NextToken; + } + if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) { + SHOW_PROGRESS(output,"Error: entry in product ID list is not a hex string: %s. " + "Ignored\n", token); + + goto NextToken; + } + product = 0; + product += (unsigned char)buffer[0]; + product <<= 8; + product += (unsigned char)buffer[1]; + if (product == descriptor.idProduct) { + SHOW_PROGRESS(output," product ID matched\n"); + + if (targetClass != 0) { + // TargetClass is set, check class of first interface + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(dev, &descriptor); + devClass = descriptor.bDeviceClass; + struct libusb_config_descriptor *config; + libusb_get_config_descriptor(dev, 0, &config); + int ifaceClass = config->interface[0].altsetting[0].bInterfaceClass; + libusb_free_config_descriptor(config); + if (devClass == 0) + devClass = ifaceClass; + else + /* Check for some quirky devices */ + if (devClass != ifaceClass) + devClass = ifaceClass; + if (devClass == targetClass) { + if (verbose) + fprintf (output," target class %02x matches\n", targetClass); + if (mode == SEARCH_TARGET) { + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } else + if (verbose) + fprintf (output," device not counted, target class reached\n"); + } else { + if (verbose) + fprintf (output," device class %02x not matching target\n", devClass); + if (mode == SEARCH_DEFAULT || mode == SEARCH_BUSDEV) { + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } + } + } else if (configuration > 0) { + // Configuration parameter is set, check device configuration + int testconfig = get_current_config_value(dev); + if (testconfig != configuration) { + if (verbose) + fprintf (output," device configuration %d not matching target\n", + testconfig); + + (*numFound)++; + right_dev = dev; + if (verbose) + fprintf (output," count device\n"); + } else + if (verbose) + fprintf (output," device not counted, target configuration reached\n"); + } else { + // Neither TargetClass nor Configuration are set + (*numFound)++; + right_dev = dev; + if (mode == SEARCH_BUSDEV) + break; + } + } + + NextToken: + token = strtok(NULL, ","); + } + } + if (listcopy != NULL) + free(listcopy); + return right_dev; +} + + +/* Autodetect bulk endpoints (ab) */ + +int find_first_bulk_endpoint(int direction) +{ + int i, j; + const struct libusb_interface_descriptor *alt; + const struct libusb_endpoint_descriptor *ep; + + for (j=0; j < active_config->bNumInterfaces; j++) { + alt = &(active_config->interface[j].altsetting[0]); + if (alt->bInterfaceNumber == Interface) { + for (i=0; i < alt->bNumEndpoints; i++) { + ep = &(alt->endpoint[i]); + if ( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK) + && ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == direction ) ) { + + return ep->bEndpointAddress; + } + } + } + } + return 0; +} + + +int get_current_config_value() +{ + SHOW_PROGRESS(output,"Get the current device configuration ...\n"); + if (active_config != NULL) { + libusb_free_config_descriptor(active_config); + active_config = NULL; + } + int ret = libusb_get_active_config_descriptor(dev, &active_config); + if (ret < 0) { + SHOW_PROGRESS(output," Determining the active configuration failed (error %d). Abort\n", ret); + abortExit(); + } + return active_config->bConfigurationValue; +} + + +int get_interface_class() +{ + int i; + for (i=0; i < active_config->bNumInterfaces; i++) { + if (active_config->interface[i].altsetting[0].bInterfaceNumber == Interface) + return active_config->interface[i].altsetting[0].bInterfaceClass; + } + return -1; +} + + +/* Parameter parsing */ + +char* ReadParseParam(const char* FileName, char *VariableName) +{ + static int numLines = 0; + static char* ConfigBuffer[MAXLINES]; + char *VarName, *Comment=NULL, *Equal=NULL; + char *FirstQuote, *LastQuote, *P1, *P2; + int Line=0; + unsigned Len=0, Pos=0; + char Str[LINE_DIM], *token, *configPos; + FILE *file = NULL; + + // Reading and storing input during the first call + if (numLines==0) { + if (strncmp(FileName,"##",2) == 0) { + if (verbose) fprintf(output,"\nRead long config from command line\n"); + // "Embedded" configuration data + configPos = (char*)FileName; + token = strtok(configPos, "\n"); + strncpy(Str,token,LINE_DIM-1); + } else { + if (strcmp(FileName, "stdin")==0) { + if (verbose) fprintf(output,"\nRead long config from stdin\n"); + file = stdin; + } else { + if (verbose) fprintf(output,"\nRead config file: %s\n", FileName); + file=fopen(FileName, "r"); + } + if (file==NULL) { + fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName); + abortExit(); + } else { + token = fgets(Str, LINE_DIM-1, file); + } + } + while (token != NULL && numLines < MAXLINES) { +// Line++; + Len=strlen(Str); + if (Len==0) + goto NextLine; + if (Str[Len-1]=='\n' or Str[Len-1]=='\r') + Str[--Len]='\0'; + Equal = strchr (Str, '='); // search for equal sign + Pos = strcspn (Str, ";#!"); // search for comment + Comment = (Pos==Len) ? NULL : Str+Pos; + if (Equal==NULL or ( Comment!=NULL and Comment<=Equal)) + goto NextLine; // Comment or irrelevant, don't save + Len=strlen(Str)+1; + ConfigBuffer[numLines] = malloc(Len*sizeof(char)); + strcpy(ConfigBuffer[numLines],Str); + numLines++; + NextLine: + if (file == NULL) { + token = strtok(NULL, "\n"); + if (token != NULL) + strncpy(Str,token,LINE_DIM-1); + } else + token = fgets(Str, LINE_DIM-1, file); + } + if (file != NULL) + fclose(file); + } + + // Now checking for parameters + Line=0; + while (Line < numLines) { + strcpy(Str,ConfigBuffer[Line]); + Equal = strchr (Str, '='); // search for equal sign + *Equal++ = '\0'; + + // String + FirstQuote=strchr (Equal, '"'); // search for double quote char + LastQuote=strrchr (Equal, '"'); + if (FirstQuote!=NULL) { + if (LastQuote==NULL) { + fprintf(stderr, "Error reading parameters from file %s - " + "Missing end quote:\n%s\n", FileName, Str); + + goto Next; + } + *FirstQuote=*LastQuote='\0'; + Equal=FirstQuote+1; + } + + // removes leading/trailing spaces + Pos=strspn (Str, " \t"); + if (Pos==strlen(Str)) { + fprintf(stderr, "Error reading parameters from file %s - " + "Missing variable name:\n%s\n", FileName, Str); + + goto Next; + } + while ((P1=strrchr(Str, ' '))!=NULL or (P2=strrchr(Str, '\t'))!=NULL) + if (P1!=NULL) *P1='\0'; + else if (P2!=NULL) *P2='\0'; + VarName=Str+Pos; + + Pos=strspn (Equal, " \t"); + if (Pos==strlen(Equal)) { + fprintf(stderr, "Error reading parameter from file %s - " + "Missing value:\n%s\n", FileName, Str); + + goto Next; + } + Equal+=Pos; + + if (strcmp(VarName, VariableName)==0) { // Found it + return Equal; + } + Next: + Line++; + } + + return NULL; +} + + +int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + + +int hex2byte(const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + + +int hexstr2bin(const char *hex, unsigned char *buffer, int len) +{ + int i; + int a; + const char *ipos = hex; + unsigned char *opos = buffer; + + for (i = 0; i < len; i++) { + a = hex2byte(ipos); + if (a < 0) + return -1; + *opos++ = (unsigned char) a; + ipos += 2; + } + return 0; +} + + +void close_all() +{ + int i; + if (Messages) { + for ( i = 0; i < MSG_DIM; i++ ) { + free(Messages[i]); + } + free(Messages); + } + if (active_config) + libusb_free_config_descriptor(active_config); + if (devh) + libusb_close(devh); + // libusb_exit will crash on Raspbian 7, crude protection +#ifndef __ARMEL__ + libusb_exit(NULL); +#endif + if (sysmode) + closelog(); +} + + +void abortExit() +{ + close_all(); + exit(1); +} + + +void printVersion() +{ + char* version = VERSION; + fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n" + " * Version %s (C) Josua Dietze 2016\n" + " * Based on libusb1/libusbx\n\n" + " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version); +} + + +void printHelp() +{ + fprintf(output,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n" + " -h, --help this help\n" + " -e, --version print version information and exit\n" + " -j, --find-mbim return config no. with MBIM interface, exit\n\n" + " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n" + " -p, --default-product NUM product ID of original mode (mandatory)\n" + " -V, --target-vendor NUM target mode vendor ID (optional)\n" + " -P, --target-product NUM target mode product ID (optional)\n" + " -C, --target-class NUM target mode device class (optional)\n" + " -b, --bus-num NUM system bus number of device (for hard ID)\n" + " -g, --device-num NUM system device number (for hard ID)\n" + " -m, --message-endpoint NUM direct the message transfer there (optional)\n" + " -M, --message-content <msg> message to send (hex number as string)\n" + " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n" + " -w, --release-delay NUM wait NUM ms before releasing the interface\n" + " -n, --need-response obsolete, no effect (always on)\n" + " -r, --response-endpoint NUM read response from there (optional)\n" + " -K, --std-eject send standard EJECT sequence\n" + " -d, --detach-only detach the active driver, no further action\n" + " -H, --huawei-mode apply a special procedure\n" + " -J, --huawei-new-mode apply a special procedure\n" + " -S, --sierra-mode apply a special procedure\n" + " -O, --sony-mode apply a special procedure\n" + " -G, --gct-mode apply a special procedure\n" + " -N, --sequans-mode apply a special procedure\n" + " -A, --mobileaction-mode apply a special procedure\n" + " -T, --kobil-mode apply a special procedure\n" + " -L, --cisco-mode apply a special procedure\n" + " -B, --qisda-mode apply a special procedure\n" + " -E, --quanta-mode apply a special procedure\n" + " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n" + " -Z, --blackberry-mode apply a special procedure\n" + " -U, --option-mode apply a special procedure\n" + " -R, --reset-usb reset the device after all other actions\n" + " -Q, --quiet don't show progress or error messages\n" + " -W, --verbose print all settings and debug output\n" + " -D, --sysmode specific result and syslog message\n" + " -s, --success <seconds> switching result check with timeout\n" + " -I, --inquire obsolete, no effect\n\n" + " -c, --config-file <filename> load long configuration from file\n\n" + " -t, --stdinput read long configuration from stdin\n\n" + " -f, --long-config <text> get long configuration from string\n\n" + " -i, --interface NUM select initial USB interface (default 0)\n" + " -u, --configuration NUM select USB configuration\n" + " -a, --altsetting NUM select alternative USB interface setting\n\n"); +} diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf new file mode 100755 index 0000000..7c68993 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.conf @@ -0,0 +1,31 @@ +# Configuration for the usb_modeswitch package, a mode switching tool for +# USB devices providing multiple states or modes +# +# Evaluated by the wrapper script /usr/sbin/usb_modeswitch_dispatcher +# +# To enable an option, set it to "1", "yes" or "true" (case doesn't matter) +# Everything else counts as "disable" + + +# Disable automatic mode switching globally (e.g. to access the original +# install storage) + +DisableSwitching=0 + +# Disable check for MBIM module presence and configuration globally (to aid +# special embedded environments) + +DisableMBIMGlobal=0 + +# Enable logging (results in a extensive report file in /var/log, named +# "usb_modeswitch_<interface-name>" and probably others + +EnableLogging=0 + + +# Optional increase of "delay_use" for the usb-storage driver; there are hints +# that a recent kernel default change to 1 sec. may lead to problems, particu- +# larly with USB 3.0 ports. Set this to at least 3 (seconds) in that case. +# Does nothing if the current system value is same or higher + +#SetStorageDelay=4 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a new file mode 100755 index 0000000..9813a20 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_002a @@ -0,0 +1,4 @@ +# HP LaserJet Professional P1102 +TargetClass=0x07 +MessageContent="555342431234567800000000000006d0000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d new file mode 100755 index 0000000..609c7a1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_521d @@ -0,0 +1,2 @@ +# HP hs3110 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d new file mode 100755 index 0000000..8b5a348 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_531d @@ -0,0 +1,2 @@ +# HP hs3120 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d new file mode 100755 index 0000000..ecb0c48 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_541d @@ -0,0 +1,2 @@ +# HP hs3114 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d new file mode 100755 index 0000000..b2f662d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_581d @@ -0,0 +1,2 @@ +# HP hs4112 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d new file mode 100755 index 0000000..ff2dcc7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_631d @@ -0,0 +1,2 @@ +# HP lt4225 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d new file mode 100755 index 0000000..131c9d7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_641d @@ -0,0 +1,2 @@ +# HP lt4226 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d new file mode 100755 index 0000000..60b7f75 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_681d @@ -0,0 +1,2 @@ +# HP lt4227 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d new file mode 100755 index 0000000..b9a6a13 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_911d @@ -0,0 +1,2 @@ +# HP lt4211 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d new file mode 100755 index 0000000..08a3290 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_931d @@ -0,0 +1,2 @@ +# HP lt4110 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d new file mode 100755 index 0000000..d3b8b9d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/03f0_9a1d @@ -0,0 +1,2 @@ +# HP lt4114 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 new file mode 100755 index 0000000..089c437 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_1000 @@ -0,0 +1,4 @@ +# Quanta MU-Q101 +TargetVendor=0x0408 +TargetProduct=0xea02 +MessageContent="55534243123456780002000000000a2a000000003300000100000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 new file mode 100755 index 0000000..562377a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea17 @@ -0,0 +1,4 @@ +# Quanta 1KR / USB-lte 7410 +TargetVendor=0x0408 +TargetProduct=0xea16 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 new file mode 100755 index 0000000..9274941 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea25 @@ -0,0 +1,4 @@ +# Quanta 1K3 LTE +TargetVendor=0x0408 +TargetProduct=0xea26 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 new file mode 100755 index 0000000..5c580e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_ea43 @@ -0,0 +1,4 @@ +# Quanta MobileGenie 4G LTE, Quanta 1K6 +TargetVendor=0x0408 +TargetProductList="ea47,ea49,ea4d" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 new file mode 100755 index 0000000..3e38133 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000 @@ -0,0 +1,4 @@ +# MU-Q110 +TargetVendor=0x0408 +TargetProduct=0xea03 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota new file mode 100755 index 0000000..0b18e44 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f000_uMa=Yota @@ -0,0 +1,4 @@ +# Yota Router (Quanta 1QDLZZZ0ST2) +TargetVendor=0x0408 +TargetProduct=0xd009 +MessageContent="5553424312345678000000000000061b004600000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 new file mode 100755 index 0000000..3cb57a0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0408_f001 @@ -0,0 +1,4 @@ +# SpeedUp SU-8500U +TargetVendor=0x0408 +TargetProduct=0xea03 +QuantaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c new file mode 100755 index 0000000..be0b8dc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_060c @@ -0,0 +1,4 @@ +# Nokia CS-10 +TargetVendor=0x0421 +TargetProduct=0x060e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 new file mode 100755 index 0000000..b2710ad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0610 @@ -0,0 +1,4 @@ +# Nokia CS-15 +TargetVendor=0x0421 +TargetProduct=0x0612 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 new file mode 100755 index 0000000..80afec0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0618 @@ -0,0 +1,4 @@ +# Nokia CS-12 +TargetVendor=0x0421 +TargetProduct=0x0619 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d new file mode 100755 index 0000000..98818a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_061d @@ -0,0 +1,4 @@ +# Nokia CS-11 +TargetVendor=0x0421 +TargetProduct=0x061e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 new file mode 100755 index 0000000..465f145 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0622 @@ -0,0 +1,4 @@ +# Nokia CS-17 +TargetVendor=0x0421 +TargetProduct=0x0623 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 new file mode 100755 index 0000000..882893b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0627 @@ -0,0 +1,4 @@ +# Nokia CS-18 +TargetVendor=0x0421 +TargetProductList="0612,0629" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c new file mode 100755 index 0000000..eb5dbde --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_062c @@ -0,0 +1,4 @@ +# Nokia CS-19 +TargetVendor=0x0421 +TargetProductList="062d,062f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 new file mode 100755 index 0000000..5ed6a7f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0632 @@ -0,0 +1,4 @@ +# Nokia CS-7M-01 +TargetVendor=0x0421 +TargetProduct=0x0632 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 new file mode 100755 index 0000000..e1415b7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0421_0637 @@ -0,0 +1,4 @@ +# Nokia CS-21M-02 +TargetVendor=0x0421 +TargetProduct=0x0638 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 new file mode 100755 index 0000000..25a45c7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/046d_c261 @@ -0,0 +1,5 @@ +# Logitech G920 Racing Wheel +MessageEndpoint=0x01 +ResponseEndpoint=0x01 +TargetClass=0x03 +MessageContent="0f00010142" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips new file mode 100755 index 0000000..74eca5a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Philips @@ -0,0 +1,3 @@ +# Philips (?) +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue new file mode 100755 index 0000000..b3cd0a7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1210_uMa=Wisue @@ -0,0 +1,4 @@ +# Vodafone MD950 (Wisue Technology) +TargetVendor=0x1dbc +TargetProduct=0x0005 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 new file mode 100755 index 0000000..e48527c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0471_1237 @@ -0,0 +1,4 @@ +# Philips TalkTalk (NXP Semiconductors "Dragonfly") +TargetVendor=0x0471 +TargetProductList="1206,1234" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d new file mode 100755 index 0000000..570794f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0482_024d @@ -0,0 +1,2 @@ +# Kyocera W06K CDMA modem +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd new file mode 100755 index 0000000..7c4e229 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04bb_bccd @@ -0,0 +1,4 @@ +# I-O Data WMX2-U Wimax +TargetVendor=0x04bb +TargetProduct=0x0949 +MessageContent="55534243f0298d8124000000800006bc626563240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 new file mode 100755 index 0000000..9d6e469 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_2251 @@ -0,0 +1,4 @@ +# Alcatel-Lucent ABS-T920 +TargetVendor=0x04cc +TargetProductList="2259,226e" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c new file mode 100755 index 0000000..3f6e8ab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_225c @@ -0,0 +1,2 @@ +# Alcatel-Lucent T930S +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e new file mode 100755 index 0000000..fe4bd3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226e @@ -0,0 +1,2 @@ +# Nexperia TM TD-SCDMA +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f new file mode 100755 index 0000000..a65c5cf --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04cc_226f @@ -0,0 +1,2 @@ +# Nexperia TM TD-SCDMA (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c new file mode 100755 index 0000000..871cbd8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_680c @@ -0,0 +1,4 @@ +# Samsung GT-B1110 +TargetVendor=0x04e8 +TargetProduct=0x6792 +MessageContent="0902200001010080fa0904000002080650000705010200020007058102000200" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a new file mode 100755 index 0000000..55977b9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_689a @@ -0,0 +1,6 @@ +# Samsung GT-B3730 +TargetVendor=0x04e8 +TargetProduct=0x6889 +MessageContent="55534243785634120100000080000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 new file mode 100755 index 0000000..c445158 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04e8_f000_sMo=U209 @@ -0,0 +1,4 @@ +# Samsung U209 +TargetVendor=0x04e8 +TargetProduct=0x6601 +MessageContent="55534243123456780000000000000616000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 new file mode 100755 index 0000000..35e00a1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/04fc_2140 @@ -0,0 +1,4 @@ +# Sunplus Techn. SU-3200U +TargetVendor=0x04fc +TargetProductList="0615,1240" +MessageContent="55534243123456782400000080000612000024000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff new file mode 100755 index 0000000..a73effb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_62ff @@ -0,0 +1,7 @@ +# AVM Fritz!Wlan USB Stick N v2 +TargetVendor=0x057c +TargetProductList="8501,8502" +# Std.Eject not working +MessageContent="5553424312345678000000000000061b000000ff0000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff new file mode 100755 index 0000000..3da7f76 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/057c_84ff @@ -0,0 +1,7 @@ +# AVM Fritz!Wlan USB Stick N +TargetVendor=0x057c +TargetProduct=0x8401 +# Std.Eject not working +MessageContent="5553424312345678000000000000061b000000ff0000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 new file mode 100755 index 0000000..d7db758 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_0010 @@ -0,0 +1,4 @@ +# Axesstel Modems (w/ initial idProduct 0x0010) +TargetVendor=0x05c6 +TargetProduct=0x00a0 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT new file mode 100755 index 0000000..330d07c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=GT @@ -0,0 +1,4 @@ +# Option GlobeTrotter GX0201 +TargetVendor=0x0af0 +TargetProduct=0x6701 +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option new file mode 100755 index 0000000..c76cde8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_sVe=Option @@ -0,0 +1,4 @@ +# Older Option devices +TargetVendor= 0x0af0 +TargetProductList="6901,6701,6600" +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA new file mode 100755 index 0000000..ea414de --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=AnyDATA @@ -0,0 +1,4 @@ +# AnyDATA devices, Bless UC165 +TargetVendor= 0x16d5 +TargetProduct=0x6502 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT new file mode 100755 index 0000000..044da01 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=CELOT @@ -0,0 +1,4 @@ +# Celot K-300 a.o. +TargetVendor=0x211f +TargetProductList="6801,6802" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd new file mode 100755 index 0000000..a4e70e8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Co.,Ltd @@ -0,0 +1,4 @@ +# TechFaith Venus VT-18 +TargetVendor=0x1d09 +TargetProduct=0x4306 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT new file mode 100755 index 0000000..8a787a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=DGT @@ -0,0 +1,4 @@ +# Celot CT-680 +TargetVendor=0x211f +TargetProduct=0x6802 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option new file mode 100755 index 0000000..0f2ce47 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Option @@ -0,0 +1,4 @@ +# Quirky Option devices +TargetVendor=0x0af0 +TargetProduct=0x6901 +OptionMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG new file mode 100755 index 0000000..bbd8a30 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SAMSUNG @@ -0,0 +1,4 @@ +# Samsung SGH-Z810 +TargetVendor= 0x04e8 +TargetProduct=0x6601 +MessageContent="55534243123456780000000000000616000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE new file mode 100755 index 0000000..8ed06ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=SSE @@ -0,0 +1,4 @@ +# Prolink P2000 CDMA +TargetVendor=0x05c6 +TargetProduct=0x6000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising new file mode 100755 index 0000000..171cae3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=StrongRising @@ -0,0 +1,4 @@ +# StrongRising device +TargetVendor= 0x028a +TargetProduct=0x1006 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex new file mode 100755 index 0000000..8fbcd80 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_1000_uMa=Vertex @@ -0,0 +1,4 @@ +# Vertex Wireless 100 Series +TargetVendor=0x1fe7 +TargetProduct=0x0100 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 new file mode 100755 index 0000000..65897a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2000 @@ -0,0 +1,6 @@ +# Various USB modems +TargetVendor=0x05c6 +TargetProductList="0015,0016,0018,ce17" +MessageContent="5553424368032c882400000080000612000000240000000000000000000000" +NeedResponse=1 +CheckSuccess=40 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 new file mode 100755 index 0000000..f13efd9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_2001 @@ -0,0 +1,4 @@ +# D-Link DWM-162-U5, DWM-162 C1, Micromax MMX 300c +TargetVendor=0x1e0e +TargetProductList="ce16,ce17,cefe" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 new file mode 100755 index 0000000..43c6217 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_6503 @@ -0,0 +1,4 @@ +# AnyDATA APE-540H +TargetVendor=0x16d5 +TargetProduct=0x6502 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 new file mode 100755 index 0000000..c809a67 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_9024 @@ -0,0 +1,4 @@ +# Alcatel-sbell ASB TL131 TD-LTE +TargetVendor=0x05c6 +TargetProduct=0x9025 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff new file mode 100755 index 0000000..72e252a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_98ff @@ -0,0 +1,4 @@ +# U901 (LTE modem) +TargetVendor=0x05c6 +TargetProduct=0x6001 +SierraMode=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 new file mode 100755 index 0000000..d064949 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c6_f000 @@ -0,0 +1,5 @@ +# Siptune LM-75 ("LinuxModem"), EWangshikong 4G +TargetVendor=0x05c6 +TargetProductList="0016,6000,9000" +StandardEject=1 +MessageContent="5553424308306384c000000080000671030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 new file mode 100755 index 0000000..9db6c68 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/05c7_1000 @@ -0,0 +1,4 @@ +# Qtronix EVDO 3G Modem (for TianYi) +TargetVendor=0x05c7 +TargetProduct=0x6000 +MessageContent="5553424312345678c00000008000069f140000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 new file mode 100755 index 0000000..d0b85b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0685_2000 @@ -0,0 +1,5 @@ +# ZE-3G 7.2Mbs HSPA modem +TargetVendor=0x1c9e +TargetProduct=0x9603 +MessageContent="5553424368032c882400000080000612000000240000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d new file mode 100755 index 0000000..95f7c45 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/072f_100d @@ -0,0 +1,7 @@ +# InfoCert Business Key (SmartCard/Reader emulation) +TargetVendor=0x072f +TargetProduct=0x90cc +MessageEndpoint=0x02 +MessageContent="01b0000000000000000000000000000000000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 new file mode 100755 index 0000000..2adc178 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a800 @@ -0,0 +1,4 @@ +# D-Link DWM-156 HSUPA 3.75G a.o. +TargetVendor=0x07d1 +TargetProductList="3e01,3e02,7e0c" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 new file mode 100755 index 0000000..6fced74 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_a804 @@ -0,0 +1,4 @@ +# D-Link DWM-156 HSUPA 3.75G USB Modem +TargetVendor=0x07d1 +TargetProduct=0x7e11 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 new file mode 100755 index 0000000..f79dba7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/07d1_f000 @@ -0,0 +1,4 @@ +# D-Link DWM-151 A1 +TargetVendor=0x07d1 +TargetProduct=0x7e07 +MessageContent="555342431234567800000000000006bd000000020000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 new file mode 100755 index 0000000..86886a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1001 @@ -0,0 +1,8 @@ +# Dymo LabelManager +TargetVendor=0x0922 +TargetProduct=0x1002 +MessageEndpoint=0x01 +ResponseEndpoint=0x01 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 new file mode 100755 index 0000000..82f42e3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1003 @@ -0,0 +1,6 @@ +# Dymo LabelManager 420P +TargetVendor= 0x0922 +TargetProduct= 0x1004 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 new file mode 100755 index 0000000..2b48fb0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0922_1007 @@ -0,0 +1,6 @@ +# Dymo LabelManager Wireless PnP +TargetVendor= 0x0922 +TargetProduct= 0x1008 +MessageContent="1b5a01" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 new file mode 100755 index 0000000..2dcca74 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0930_0d46 @@ -0,0 +1,4 @@ +# Toshiba G450 +TargetVendor=0x0930 +TargetProduct=0x0d45 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 new file mode 100755 index 0000000..9b5a78f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_2011 @@ -0,0 +1,4 @@ +# Zydas ZD1211RW WLAN USB, Sphairon HomeLink 1202 (Variant 1) +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff new file mode 100755 index 0000000..55178af --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0ace_20ff @@ -0,0 +1,4 @@ +# Zydas ZD1211RW WLAN USB, Sphairon HomeLink 1202 (Variant 2) +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 new file mode 100755 index 0000000..d209494 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_4007 @@ -0,0 +1,6 @@ +# Option iCon 711 +TargetVendor=0x0af0 +TargetProduct=0x4005 +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6711 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6731 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6751 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6771 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6791 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6811 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6911 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6951 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_6971 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7011 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7051 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7071 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7111 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7211 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7251 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7271 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7301 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7311 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7361 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7381 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7401 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7501 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7601 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7701 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7706 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7801 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7901 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a01 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 new file mode 100755 index 0000000..ffaea9c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_7a05 @@ -0,0 +1,5 @@ +# Option iCon 461 +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 new file mode 100755 index 0000000..ccdd7f5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8006 @@ -0,0 +1,6 @@ +# Option Globetrotter (Variant) +TargetVendor=0x0af0 +TargetProduct=0x9100 +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8200 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8201 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8300 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8302 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8304 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8400 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8600 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 new file mode 100755 index 0000000..2d73b1c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8700 @@ -0,0 +1,5 @@ +# Option GI0643 (aka XYFI) +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8800 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_8900 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9000 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_9200 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_c100 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 new file mode 100755 index 0000000..4f2b39e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d001 @@ -0,0 +1,6 @@ +# Option GlobeTrotter GI1515 +TargetVendor=0x0af0 +TargetProductList="d157,d255,d257" +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d013 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d031 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d033 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d035 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d055 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d057 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d058 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d155 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d157 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d255 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d257 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 new file mode 100755 index 0000000..1a21ca2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0af0_d357 @@ -0,0 +1,5 @@ +# Option HSO device +TargetClass=0xff +OptionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 new file mode 100755 index 0000000..fd4da50 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_c700 @@ -0,0 +1,4 @@ +# Olivetti Olicard 100 and others +TargetVendor=0x0b3c +TargetProductList="c000,c001,c002" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 new file mode 100755 index 0000000..b17d1eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f000 @@ -0,0 +1,5 @@ +# Olivetti Olicard 145, 155 +TargetVendor=0x0b3c +TargetProductList="c003,c004" +MessageContent="5553424312345678c000000080010606f50402527000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c new file mode 100755 index 0000000..00f1298 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f00c @@ -0,0 +1,4 @@ +# Olivetti Olicard 160 +TargetVendor=0x0b3c +TargetProduct=0xc00a +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 new file mode 100755 index 0000000..72df51d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0b3c_f017 @@ -0,0 +1,4 @@ +# Olivetti Olicard 500 +TargetVendor=0x0b3c +TargetProduct=0xc00b +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d new file mode 100755 index 0000000..aa901b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_190d @@ -0,0 +1,2 @@ +# Ericsson F5521gw +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 new file mode 100755 index 0000000..5e9049e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0bdb_1910 @@ -0,0 +1,2 @@ +# Ericsson F5521gw (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff new file mode 100755 index 0000000..3ce9058 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0cf3_20ff @@ -0,0 +1,6 @@ +# Atheros Wireless / Netgear WNDA3200 +TargetVendor=0x0cf3 +TargetProduct=0x7010 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 new file mode 100755 index 0000000..1d82e3f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a1 @@ -0,0 +1,4 @@ +# Kobil mIdentity 3G (1) +TargetVendor=0x0d46 +TargetProduct=0x45a9 +KobilMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 new file mode 100755 index 0000000..2074a95 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0d46_45a5 @@ -0,0 +1,4 @@ +# Kobil mIdentity 3G (2) +TargetVendor=0x0d46 +TargetProduct=0x45ad +KobilMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 new file mode 100755 index 0000000..826501c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0df7_0800 @@ -0,0 +1,5 @@ +# Mobile Action ("Smart Cable") +TargetClass=0xff +MobileActionMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT new file mode 100755 index 0000000..f23f468 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=MT @@ -0,0 +1,4 @@ +# MediaTek MT6276M and others +TargetVendor=0x0e8d +TargetProductList="00a1,00a2,00a5" +MessageContent="555342431234567800000000000006f0010300000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product new file mode 100755 index 0000000..f36fa83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_0002_uPr=Product @@ -0,0 +1,4 @@ +# MediaTek/Medion S4222 and probably others +TargetVendor=0x0e8d +TargetProductList="00a1,00a2,00a5" +MessageContent="555342431234567800000000000006f0010300000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 new file mode 100755 index 0000000..a71557f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0e8d_7109 @@ -0,0 +1,6 @@ +# MediaTek Wimax USB Card +TargetVendor=0x0e8d +TargetProductList="7115,7118" +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 new file mode 100755 index 0000000..7a07ad9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fca_8020 @@ -0,0 +1,4 @@ +# BlackBerry Q10 and Z10 +TargetVendor=0x0fca +TargetProduct=0x8012 +BlackberryMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf new file mode 100755 index 0000000..85dc2c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0cf @@ -0,0 +1,2 @@ +# Sony Ericsson MD300 +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df new file mode 100755 index 0000000..4bb9dca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0df @@ -0,0 +1,2 @@ +# Sony Ericsson EC400 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 new file mode 100755 index 0000000..f3e9e86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d0e1 @@ -0,0 +1,4 @@ +# Sony Ericsson MD400 +TargetClass=0x02 +SonyMode=1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 new file mode 100755 index 0000000..cc9e7a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fce_d103 @@ -0,0 +1,4 @@ +# Sony Ericsson MD400G +TargetClass=0x02 +SonyMode=1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 new file mode 100755 index 0000000..04101aa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/0fd1_1000 @@ -0,0 +1,2 @@ +# GW D301 (Advinne AMC) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 new file mode 100755 index 0000000..4468271 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_1000 @@ -0,0 +1,3 @@ +# LG LDU-1900D EV-DO (Rev. A) +TargetClass=0xff +MessageContent="55534243123456780000000000000aff554d53434847000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f new file mode 100755 index 0000000..25ccde5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_607f @@ -0,0 +1,5 @@ +# LG HDM-2100 (EVDO Rev.A USB modem) +TargetVendor=0x1004 +TargetProductList="6000,6114" +MessageContent="555342431234567803000000800006f1010100000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c new file mode 100755 index 0000000..dc25e1f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_610c @@ -0,0 +1,4 @@ +# LG L-02A +TargetVendor=0x1004 +TargetProduct=0x6109 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a new file mode 100755 index 0000000..02bc44b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613a @@ -0,0 +1,4 @@ +# LG L-05A +TargetVendor=0x1004 +TargetProduct=0x6124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f new file mode 100755 index 0000000..ce75c58 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_613f @@ -0,0 +1,4 @@ +# LG LUU-2100TI (aka AT&T USBConnect Turbo) +TargetVendor=0x1004 +TargetProduct=0x6141 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e new file mode 100755 index 0000000..0492200 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_614e @@ -0,0 +1,4 @@ +# LG L-07A +TargetVendor=0x1004 +TargetProduct=0x6135 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 new file mode 100755 index 0000000..89b1b85 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6156 @@ -0,0 +1,4 @@ +# LG LUU-2110TI +TargetVendor=0x1004 +TargetProduct=0x6157 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 new file mode 100755 index 0000000..4334c0a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6190 @@ -0,0 +1,5 @@ +# LG AD600 +TargetVendor=0x1004 +TargetProduct=0x61a7 +WaitBefore=10 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa new file mode 100755 index 0000000..0db0efb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61aa @@ -0,0 +1,4 @@ +# LG VL600 +TargetVendor=0x1004 +TargetProduct=0x61a7 +StandardEject=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd new file mode 100755 index 0000000..2ccd9bc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61dd @@ -0,0 +1,4 @@ +# LG L-02C LTE +TargetVendor=0x1004 +TargetProduct=0x618f +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 new file mode 100755 index 0000000..097e7e2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61e7 @@ -0,0 +1,4 @@ +# LG SD711 +TargetVendor=0x1004 +TargetProduct=0x61e6 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb new file mode 100755 index 0000000..10f1591 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_61eb @@ -0,0 +1,4 @@ +# LG L-08C (NTT docomo) +TargetVendor=0x1004 +TargetProduct=0x61ea +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 new file mode 100755 index 0000000..f34ce2a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1004_6327 @@ -0,0 +1,4 @@ +# LG L-03D LTE/3G +TargetVendor=0x1004 +TargetProduct=0x6326 +MessageContent=555342431234567800000000000005f1010100000000000000000000000000 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 new file mode 100755 index 0000000..2541fd2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1033_0035 @@ -0,0 +1,4 @@ +# Huawei E630 +TargetVendor=0x12d1 +TargetProduct=0x1003 +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 new file mode 100755 index 0000000..4201228 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b03 @@ -0,0 +1,4 @@ +# UTStarcom UM175 (distributor "Alltel") +TargetVendor=0x106c +TargetProduct=0x3715 +MessageContent="555342431234567824000000800008ff024445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 new file mode 100755 index 0000000..e7f732d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b05 @@ -0,0 +1,4 @@ +# Pantech / UTStarcom UMW190 (Verizon) +TargetVendor=0x106c +TargetProduct=0x3716 +MessageContent="555342431234567824000000800008ff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 new file mode 100755 index 0000000..9351e41 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b06 @@ -0,0 +1,4 @@ +# UTStarcom UM185E (distributor "Alltel") +TargetVendor=0x106c +TargetProduct=0x3717 +MessageContent="55534243b82e238c24000000800008ff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 new file mode 100755 index 0000000..7ebbf49 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b11 @@ -0,0 +1,4 @@ +# Pantech UML290 +TargetVendor=0x106c +TargetProduct=0x3718 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 new file mode 100755 index 0000000..eb351af --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/106c_3b14 @@ -0,0 +1,6 @@ +# Option Beemo / Pantech P4200 LTE +TargetVendor=0x106c +TargetProduct=0x3721 +MessageContent="555342431234567824000000800008ff024445564348470000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 new file mode 100755 index 0000000..60e9117 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1076_7f40 @@ -0,0 +1,4 @@ +# Sagem F@ST 9520-35-GLR +TargetVendor=0x1076 +TargetProduct=0x7f00 +GCTMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 new file mode 100755 index 0000000..7d1e2c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/109b_f009 @@ -0,0 +1,4 @@ +# Hisense E910 EVDO Phone +TargetVendor=0x109b +TargetProduct=0x9114 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f new file mode 100755 index 0000000..45dda80 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_606f @@ -0,0 +1,7 @@ +# Pantech/Verizon UML295 +TargetVendor=0x10a9 +TargetProductList="6064,6074" +# Use 1 for automatic choice, 2 for RNDIS, 4 for QMI +PantechMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 new file mode 100755 index 0000000..3883005 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/10a9_6080 @@ -0,0 +1,4 @@ +# Pantech LTE Modem +TargetVendor=0x10a9 +TargetProduct=0x6085 +PantechMode=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff new file mode 100755 index 0000000..88c8882 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_0fff @@ -0,0 +1,6 @@ +# Sierra devices (specific driver) +TargetVendor= 0x1199 +TargetProductList="0017,0018,0019,0020,0021,0022,0023,0024,0025,0026,0027,0028,0029,0112,0120,0218,0220,0224,0301,6802,6803,6804,6805,6808,6809,6812,6813,6815,6816,6820,6821,6822,6832,6833,6834,6835,6838,6839,683a,683b,683c,683d,683e,6850,6851,6852,6853,6855,6856,6859,685a,6880,6890,6891,6892,6893,68a2,68a3,68aa,9011,9012,9051" +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 new file mode 100755 index 0000000..e1ac1fe --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9011 @@ -0,0 +1,4 @@ +# Sierra MC8305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 new file mode 100755 index 0000000..d60fac0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9013 @@ -0,0 +1,4 @@ +# Sierra MC8355 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 new file mode 100755 index 0000000..d33a899 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9017 @@ -0,0 +1,4 @@ +# Sierra MC8355 Variant +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b new file mode 100755 index 0000000..f291e83 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901b @@ -0,0 +1,4 @@ +# Sierra MC7770 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c new file mode 100755 index 0000000..3a13e2f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901c @@ -0,0 +1,4 @@ +# Sierra EM7700 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f new file mode 100755 index 0000000..ca03f4c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_901f @@ -0,0 +1,4 @@ +# Sierra EM7355 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 new file mode 100755 index 0000000..2389f40 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9041 @@ -0,0 +1,4 @@ +# Sierra EM7305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 new file mode 100755 index 0000000..0e10ef2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9051 @@ -0,0 +1,4 @@ +# Sierra AC340U +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 new file mode 100755 index 0000000..debd945 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9053 @@ -0,0 +1,4 @@ +# Sierra AC770S +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 new file mode 100755 index 0000000..2389f40 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1199_9063 @@ -0,0 +1,4 @@ +# Sierra EM7305 +Configuration=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 new file mode 100755 index 0000000..cf859d0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1266_1000 @@ -0,0 +1,4 @@ +# Digicom 8E4455 (and all Pirelli devices - EXPERIMENTAL) +TargetVendor=0x1266 +TargetProductList="1002,1003,1004,1005,1006,1007,1008,1009,100a,100b,100c,100d,100e,100f,1011,1012" +StandardEject=1 diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" new file mode 100755 index 0000000..f7d7928 --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043android" @@ -0,0 +1,3 @@ +# Huawei generic for Android +TargetVendor= 0x12d1 +MessageContent="55534243123456780000000000000011063000000100010000000000000000" diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" new file mode 100755 index 0000000..78e7ea5 --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_\043linux" @@ -0,0 +1,3 @@ +# Huawei generic for Linux (fall-back for unknown products) +TargetVendor= 0x12d1 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 new file mode 100755 index 0000000..273c035 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1001 @@ -0,0 +1,3 @@ +# Huawei E169 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 new file mode 100755 index 0000000..5c37062 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1003 @@ -0,0 +1,3 @@ +# Huawei E220, E230, E270, E870 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 new file mode 100755 index 0000000..2b03464 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1009 @@ -0,0 +1,3 @@ +# Huawei V725 Phone (aka Vodafone 725) +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 new file mode 100755 index 0000000..c7c1d03 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1010 @@ -0,0 +1,3 @@ +# Huawei ETS1201 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e new file mode 100755 index 0000000..dae8e2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_101e @@ -0,0 +1,3 @@ +# Huawei U7510 / U7517 +TargetClass=0xff +MessageContent="55534243123456780600000080000601000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 new file mode 100755 index 0000000..d5c73d7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1030 @@ -0,0 +1,6 @@ +# Huawei U8220, T-Mobile Pulse (Android smartphone) +TargetVendor=0x12d1 +TargetProduct=0x1034 +MessageContent="55534243123456780600000080010a11060000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 new file mode 100755 index 0000000..cc262da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1031 @@ -0,0 +1,7 @@ +# Huawei U8110 / Joy, Vodafone 845 (Android smartphone) +TargetVendor=0x12d1 +TargetProduct=0x1035 +MessageContent="55534243123456780600000080010a11060000000000000000000000000000" +# for Android SDK + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 new file mode 100755 index 0000000..1158582 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1413 @@ -0,0 +1,3 @@ +# Huawei EC168 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 new file mode 100755 index 0000000..742d75d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1414 @@ -0,0 +1,3 @@ +# Huawei E180 +TargetClass=0xff +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 new file mode 100755 index 0000000..48c6d35 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1446 @@ -0,0 +1,4 @@ +# Huawei, newer modems, and rebrandings +TargetVendor=0x12d1 +TargetProductList="1001,1404,1406,140b,140c,1412,1417,141b,1429,1432,1433,1436,14ac,1506,150c,1511" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 new file mode 100755 index 0000000..1713857 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1449 @@ -0,0 +1,4 @@ +# Huawei E352 +TargetVendor=0x12d1 +TargetProduct=0x1444 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad new file mode 100755 index 0000000..e3d4328 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ad @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K3806 +TargetVendor=0x12d1 +TargetProduct=0x14ae +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 new file mode 100755 index 0000000..322da5f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b5 @@ -0,0 +1,4 @@ +# Huawei E173 (Viettel 3G) +TargetVendor=0x12d1 +TargetProductList="14a8,14aa" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 new file mode 100755 index 0000000..e9f7cee --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14b7 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4511 +TargetVendor=0x12d1 +TargetProduct=0x14cc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba new file mode 100755 index 0000000..a2c257e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14ba @@ -0,0 +1,4 @@ +# Huawei E173u-2, E177 +TargetVendor=0x12d1 +TargetProduct=0x14d2 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 new file mode 100755 index 0000000..309830f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c1 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4605 +TargetVendor=0x12d1 +TargetProduct=0x14c6 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 new file mode 100755 index 0000000..413e8d2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c3 @@ -0,0 +1,4 @@ +# K5005 Vodafone/Huawei +TargetVendor=0x12d1 +TargetProduct=0x14c8 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 new file mode 100755 index 0000000..e7ffc66 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c4 @@ -0,0 +1,4 @@ +# Vodafone/Huawei K3771 +TargetVendor=0x12d1 +TargetProduct=0x14ca +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 new file mode 100755 index 0000000..17ecd3c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14c5 @@ -0,0 +1,4 @@ +# Vodafone (Huawei) K4510 +TargetVendor=0x12d1 +TargetProduct=0x14cb +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 new file mode 100755 index 0000000..2ab14e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14d1 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3770 +TargetVendor=0x12d1 +TargetProduct=0x14c9 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe new file mode 100755 index 0000000..9c16d2a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_14fe @@ -0,0 +1,4 @@ +# Huawei E352 (T-Mobile NL), E173s (Variant) +TargetVendor=0x12d1 +TargetProductList="1506,150f,151d,1c1e" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 new file mode 100755 index 0000000..ab5e1cd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1505 @@ -0,0 +1,4 @@ +# Huawei EC156, Huawei E372u-8 +TargetVendor=0x12d1 +TargetProductList="140b,140c,1506,150f,150a" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a new file mode 100755 index 0000000..283ae5b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_151a @@ -0,0 +1,4 @@ +# Huawei E392u-12, E3131 (Variant) +TargetVendor=0x12d1 +TargetProductList="151b,151d,151e" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 new file mode 100755 index 0000000..d03f821 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1520 @@ -0,0 +1,4 @@ +# Huawei K3765 +TargetVendor=0x12d1 +TargetProduct=0x1465 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 new file mode 100755 index 0000000..620690c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1521 @@ -0,0 +1,4 @@ +# Huawei K4505 +TargetVendor=0x12d1 +TargetProduct=0x1464 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 new file mode 100755 index 0000000..0eb4b7a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1523 @@ -0,0 +1,4 @@ +# Huawei R201 +TargetVendor=0x12d1 +TargetProduct=0x1491 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 new file mode 100755 index 0000000..60b8457 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1526 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3772 +TargetVendor=0x12d1 +TargetProduct=0x14cf +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 new file mode 100755 index 0000000..84fe445 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1527 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R206 Router +TargetVendor=0x12d1 +TargetProduct=0x1594 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 new file mode 100755 index 0000000..0d2552e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1553 @@ -0,0 +1,4 @@ +# Huawei E1553 +TargetVendor=0x12d1 +TargetProduct=0x1001 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 new file mode 100755 index 0000000..beef342 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1557 @@ -0,0 +1,4 @@ +# Huawei E173 +TargetVendor=0x12d1 +TargetProduct=0x14a5 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a new file mode 100755 index 0000000..451a8f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155a @@ -0,0 +1,4 @@ +# Vodafone (Huawei) R205 +TargetVendor=0x12d1 +TargetProduct=0x14cd +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b new file mode 100755 index 0000000..d10d02d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_155b @@ -0,0 +1,4 @@ +# Huawei E171 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a new file mode 100755 index 0000000..55e6d38 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_156a @@ -0,0 +1,4 @@ +# Huawei E3276s-151 and E3251 +TargetVendor=0x12d1 +TargetProductList="156b,156c" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 new file mode 100755 index 0000000..5b8ac78 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1570 @@ -0,0 +1,2 @@ +# Huawei ME906E +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 new file mode 100755 index 0000000..2b2eb6b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1571 @@ -0,0 +1,2 @@ +# Huawei EM820W +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 new file mode 100755 index 0000000..20b6e2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1572 @@ -0,0 +1,2 @@ +# Huawei MU733 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 new file mode 100755 index 0000000..0397c2e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1573 @@ -0,0 +1,2 @@ +# Huawei ME909u-521 (MBIM, handled by kernel, dummy config) +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c new file mode 100755 index 0000000..35d811d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157c @@ -0,0 +1,4 @@ +# Huawei E3276-s150 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d new file mode 100755 index 0000000..f42d3b8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_157d @@ -0,0 +1,4 @@ +# Huawei E3331, E3372 +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 new file mode 100755 index 0000000..9b27048 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1580 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R210 Router +TargetVendor=0x12d1 +TargetProduct=0x1585 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 new file mode 100755 index 0000000..507ab0e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1581 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R208 Router +TargetVendor=0x12d1 +TargetProduct=0x1587 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 new file mode 100755 index 0000000..c8588a8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1582 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R215 Router +TargetVendor=0x12d1 +TargetProduct=0x1588 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 new file mode 100755 index 0000000..d45b089 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1583 @@ -0,0 +1,4 @@ +# Vodafone / Huawei W5101 Router +TargetVendor=0x12d1 +TargetProduct=0x1589 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 new file mode 100755 index 0000000..0a91c2d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1597 @@ -0,0 +1,4 @@ +# Huawei E327s-150 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x1598 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb new file mode 100755 index 0000000..d6b1add --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15bb @@ -0,0 +1,2 @@ +# Huawei ME936 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 new file mode 100755 index 0000000..c0b7769 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c0 @@ -0,0 +1,2 @@ +# Huawei ME906C +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 new file mode 100755 index 0000000..24e2ec0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15c1 @@ -0,0 +1,2 @@ +# Huawei ME906, ME909 (MBIM, handled by kernel, dummy config) +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca new file mode 100755 index 0000000..cf9da86 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ca @@ -0,0 +1,4 @@ +# Huawei E3131 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd new file mode 100755 index 0000000..28a5fc3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cd @@ -0,0 +1,4 @@ +# Huawei E3372 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce new file mode 100755 index 0000000..3ec6ce3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15ce @@ -0,0 +1,4 @@ +# Huawei E3531s-2, E3131 (Variant) +TargetVendor=0x12d1 +TargetProductList="15b1,15b3" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf new file mode 100755 index 0000000..7addb2d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15cf @@ -0,0 +1,4 @@ +# Huawei E3372s-153 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 new file mode 100755 index 0000000..5d2ee64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d0 @@ -0,0 +1,4 @@ +# Huawei E3131 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x15d1 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 new file mode 100755 index 0000000..94bbbac --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15d2 @@ -0,0 +1,4 @@ +# Huawei E3531 (Variant) +TargetVendor=0x12d1 +TargetProduct=0x15d3 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 new file mode 100755 index 0000000..6be0d6f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15e7 @@ -0,0 +1,4 @@ +# Huawei E3531 +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 new file mode 100755 index 0000000..c98abfd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_15f0 @@ -0,0 +1,2 @@ +# Huawei MU736 +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 new file mode 100755 index 0000000..d408152 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1805 @@ -0,0 +1,3 @@ +# Huawei U2800 Phone +TargetClass=0xff +MessageContent="55534243123456780600000080000601000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b new file mode 100755 index 0000000..c6bb69f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c0b @@ -0,0 +1,4 @@ +# Huawei E173s +TargetVendor=0x12d1 +TargetProductList="1c05,1c06,1c07,1c08,1c10" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b new file mode 100755 index 0000000..3773123 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c1b @@ -0,0 +1,6 @@ +# Huawei GP02 (E587 Variant) +TargetVendor=0x12d1 +TargetProduct=0x1506 +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 new file mode 100755 index 0000000..3b9f196 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c24 @@ -0,0 +1,4 @@ +# Huawei E173 (Moviestar), E173s (Variant) +TargetVendor=0x12d1 +TargetProductList="1c12,1c23" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 new file mode 100755 index 0000000..fa88d4d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1c25 @@ -0,0 +1,2 @@ +# Huawei MU709s-2 Module +Configuration=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 new file mode 100755 index 0000000..b218355 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1d50 @@ -0,0 +1,2 @@ +# Huawei ET302 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 new file mode 100755 index 0000000..3bb1cab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1da1 @@ -0,0 +1,4 @@ +# Huawei ET8282, Huawei ET127 +TargetVendor=0x12d1 +TargetProduct=0x1d09 +HuaweiMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 new file mode 100755 index 0000000..68cea57 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f01 @@ -0,0 +1,6 @@ +# Huawei E353 (3.se) and others +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 new file mode 100755 index 0000000..32a87b0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f02 @@ -0,0 +1,6 @@ +# Huawei E5377 +TargetVendor=0x12d1 +TargetProduct=0x14dc +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 new file mode 100755 index 0000000..a9db535 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f03 @@ -0,0 +1,6 @@ +# KDDI (Huawei) HWD12 LTE +TargetVendor=0x12d1 +TargetProduct=0x14db +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 new file mode 100755 index 0000000..aad96a9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f04 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R206_MR Router +TargetVendor=0x12d1 +TargetProduct=0x15bc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 new file mode 100755 index 0000000..cbde895 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f05 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R207 Router +TargetVendor=0x12d1 +TargetProduct=0x15bd +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 new file mode 100755 index 0000000..844e858 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f06 @@ -0,0 +1,4 @@ +# Vodafone / Huawei R215_MR Router +TargetVendor=0x12d1 +TargetProduct=0x15c7 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 new file mode 100755 index 0000000..0a023f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f07 @@ -0,0 +1,6 @@ +# Huawei/Vodafone R226 +TargetVendor=0x12d1 +TargetProduct=0x15bf +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 new file mode 100755 index 0000000..6a99608 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f09 @@ -0,0 +1,6 @@ +# Huawei/Vodafone R216 +TargetVendor=0x12d1 +TargetProduct=0x1c50 +HuaweiNewMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 new file mode 100755 index 0000000..0786aad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f11 @@ -0,0 +1,4 @@ +# Vodafone / Huawei K3773 +TargetVendor=0x12d1 +TargetProduct=0x14bc +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 new file mode 100755 index 0000000..93de9b3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f15 @@ -0,0 +1,4 @@ +# Vodafone K4305 +TargetVendor=0x12d1 +TargetProductList="1400,14f7" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 new file mode 100755 index 0000000..a32d517 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f16 @@ -0,0 +1,4 @@ +# Vodafone K5150 +TargetVendor=0x12d1 +TargetProductList="14f8,1575" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 new file mode 100755 index 0000000..e31f0b4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f17 @@ -0,0 +1,4 @@ +# Vodafone K4201 +TargetVendor=0x12d1 +TargetProduct=0x1576 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 new file mode 100755 index 0000000..767644a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f18 @@ -0,0 +1,4 @@ +# Vodafone K4202 +TargetVendor=0x12d1 +TargetProduct=0x1577 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 new file mode 100755 index 0000000..b823b1a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f19 @@ -0,0 +1,4 @@ +# Vodafone K4606 +TargetVendor=0x12d1 +TargetProductList="14fa,1575,1578" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b new file mode 100755 index 0000000..6068a4c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1b @@ -0,0 +1,4 @@ +# Vodafone / Huawei Kxxxx +TargetVendor=0x12d1 +TargetProduct=0x1579 +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c new file mode 100755 index 0000000..cf43358 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1c @@ -0,0 +1,4 @@ +# Vodafone / Huawei K4203 +TargetVendor=0x12d1 +TargetProductList="157a,1590" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d new file mode 100755 index 0000000..eb4c393 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1d @@ -0,0 +1,4 @@ +# Vodafone / Huawei Kxxxx +TargetVendor=0x12d1 +TargetProductList="157b,1591" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e new file mode 100755 index 0000000..a20456a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_1f1e @@ -0,0 +1,4 @@ +# Vodafone / Huawei K5160 +TargetVendor=0x12d1 +TargetProductList="157f,1592" +HuaweiNewMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b new file mode 100755 index 0000000..293ec72 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/12d1_380b @@ -0,0 +1,3 @@ +# Huawei BM358 WiMAX +TargetClass=0x02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 new file mode 100755 index 0000000..823c9ec --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1307_1169 @@ -0,0 +1,6 @@ +# Cisco AM10 "Valet Connector" +TargetVendor=0x13b1 +TargetProduct=0x0031 +CiscoMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 new file mode 100755 index 0000000..56ec385 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5010 @@ -0,0 +1,4 @@ +# Novatel Wireless devices +TargetVendor=0x1410 +TargetProductList="4100,4400,7030" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 new file mode 100755 index 0000000..884787a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5020 @@ -0,0 +1,4 @@ +# Novatel MC990D +TargetVendor=0x1410 +TargetProductList="6000,7001" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 new file mode 100755 index 0000000..ffe9b64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5023 @@ -0,0 +1,4 @@ +# Novatel MC996D +TargetVendor=0x1410 +TargetProduct=0x7030 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 new file mode 100755 index 0000000..ffc730a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5030 @@ -0,0 +1,4 @@ +# Novatel U760 +TargetVendor=0x1410 +TargetProduct=0x6000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 new file mode 100755 index 0000000..6f0fe13 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5031 @@ -0,0 +1,4 @@ +# Novatel MC760 3G +TargetVendor=0x1410 +TargetProduct=0x6002 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 new file mode 100755 index 0000000..747a4ce --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5041 @@ -0,0 +1,4 @@ +# Novatel Generic MiFi 2352 / Vodafone MiFi 2352 +TargetVendor=0x1410 +TargetProductList="7001,7003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 new file mode 100755 index 0000000..bce995d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5055 @@ -0,0 +1,4 @@ +# Novatel MiFi 4082 +TargetVendor=0x1410 +TargetProduct=0x6032 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 new file mode 100755 index 0000000..e191387 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_5059 @@ -0,0 +1,4 @@ +# Novatel Wireless MC545 HSPA, U679 LTE +TargetVendor=0x1410 +TargetProductList="7031,7042" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 new file mode 100755 index 0000000..e02f95e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_7001 @@ -0,0 +1,3 @@ +# Novatel Generic MiFi 2372 / Vodafone MiFi 2372 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 new file mode 100755 index 0000000..ba50114 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1410_9020 @@ -0,0 +1,2 @@ +# Novatel U620L +Configuration=4 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 new file mode 100755 index 0000000..6ff409b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148e_a000 @@ -0,0 +1,3 @@ +# Sequans SQN1210/SQN1220 (generic chipsets) +TargetClass=0x02 +SequansMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 new file mode 100755 index 0000000..7fd5163 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/148f_2578 @@ -0,0 +1,6 @@ +# Motorola 802.11 bg WLAN (TER/GUSB3-E) +TargetVendor=0x148f +TargetProduct=0x9021 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 new file mode 100755 index 0000000..2969bd8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/15eb_7153 @@ -0,0 +1,4 @@ +# China TeleCom CBP7.0 +TargetVendor=0x15eb +TargetProduct=0x7152 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 new file mode 100755 index 0000000..9dd94a0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0800 @@ -0,0 +1,5 @@ +# Amoi H-01 +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 new file mode 100755 index 0000000..67d5946 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1614_0802 @@ -0,0 +1,5 @@ +# Amoi H-02 +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 new file mode 100755 index 0000000..b140d0f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d5_f000 @@ -0,0 +1,4 @@ +# Anydata ADU-890WH +TargetVendor=0x16d5 +TargetProduct=0x6603 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 new file mode 100755 index 0000000..97c0773 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6281 @@ -0,0 +1,3 @@ +# C-motech CHU-628S +TargetClass=0xff +MessageContent="555342431234567824000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 new file mode 100755 index 0000000..bbe9bca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6803 @@ -0,0 +1,3 @@ +# C-motech D-50 (aka "CDU-680", "CNU-680") +TargetClass=0x02 +MessageContent="555342431234567824000000800008ff524445564348473100000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 new file mode 100755 index 0000000..0b0220b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_6804 @@ -0,0 +1,3 @@ +# C-motech CDU-685a +TargetClass=0xff +MessageContent="555342431234567824000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a new file mode 100755 index 0000000..f0375c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700a @@ -0,0 +1,3 @@ +# C-motech CHU-629S +TargetClass=0xff +MessageContent="55534243123456782400000080000dfe524445564348473d4e444953000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b new file mode 100755 index 0000000..b006d06 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_700b @@ -0,0 +1,3 @@ +# C-motech CHU-629S (Variant) +TargetClass=0xff +MessageContent="55534243123456782400000080000dfe524445564348473d4e444953000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 new file mode 100755 index 0000000..540292f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/16d8_f000 @@ -0,0 +1,4 @@ +# C-motech CGU-628 (aka "Franklin Wireless CGU-628A" aka "4G Systems XS Stick W12") +TargetVendor=0x16d8 +TargetProduct=0x6006 +MessageContent="55534243d85dd88524000000800008ff524445564348470000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 new file mode 100755 index 0000000..fd8acfd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_1900 @@ -0,0 +1,4 @@ +# Axesstel MV210 +TargetVendor=0x1726 +TargetProduct=0x1000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e new file mode 100755 index 0000000..abdbe53 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1726_f00e @@ -0,0 +1,4 @@ +# Axesstel MU130 +TargetVendor=0x1726 +TargetProduct=0xa000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 new file mode 100755 index 0000000..22556bd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0003 @@ -0,0 +1,2 @@ +# Spreadtrum SC7702 +Configuration=2 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 new file mode 100755 index 0000000..e5f0e4a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1782_0023 @@ -0,0 +1,2 @@ +# Spreadtrum SC7702 (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 new file mode 100755 index 0000000..2a88764 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198a_0003 @@ -0,0 +1,4 @@ +# JOA Telecom LM-700r +TargetVendor=0x198a +TargetProduct=0x0002 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd new file mode 100755 index 0000000..20e6c85 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/198f_bccd @@ -0,0 +1,6 @@ +# Beceem BCSM250 +TargetVendor=0x198f +TargetProduct=0x0220 +MessageContent="55534243f0298d8124000000800006bc626563240000000000000000000000" + + diff --git "a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" new file mode 100755 index 0000000..ec66b7d --- /dev/null +++ "b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_\043linux" @@ -0,0 +1,7 @@ +# ZTE generic for Linux (fall-back for unknown products) + +# Uncomment the following lines to activate + +#TargetVendor= 0x19d2 +#StandardEject=1 +#MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 new file mode 100755 index 0000000..1e1f24a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0003 @@ -0,0 +1,3 @@ +# ZTE MU351 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 new file mode 100755 index 0000000..3d90363 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0026 @@ -0,0 +1,4 @@ +# ZTE AC581 +TargetVendor=0x19d2 +TargetProductList="0073,0094,0152" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 new file mode 100755 index 0000000..6600b33 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0040 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K2525 +TargetVendor=0x19d2 +TargetProduct=0x0022 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 new file mode 100755 index 0000000..8c19d56 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0053 @@ -0,0 +1,4 @@ +# ZTE MF110 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0031 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA new file mode 100755 index 0000000..3ce0285 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0083_uPr=WCDMA @@ -0,0 +1,4 @@ +# ZTE MF110 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 new file mode 100755 index 0000000..4c078d8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0101 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K4505-Z +TargetVendor=0x19d2 +TargetProduct=0x0104 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 new file mode 100755 index 0000000..214f5c0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0103 @@ -0,0 +1,4 @@ +# ZTE MF112 +TargetVendor=0x19d2 +TargetProduct=0x0031 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 new file mode 100755 index 0000000..e929a64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0110 @@ -0,0 +1,5 @@ +# ZTE MF637 (Variant for Orange France) +TargetVendor=0x19d2 +TargetProduct=0x0121 +StandardEject=1 + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 new file mode 100755 index 0000000..ae1468e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0115 @@ -0,0 +1,4 @@ +# ZTE MF651 +TargetVendor=0x19d2 +TargetProduct=0x0116 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 new file mode 100755 index 0000000..5003cfc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0120 @@ -0,0 +1,7 @@ +#ZTE-T A356 +TargetVendor=0x19d2 +TargetProduct=0x0079 +DetachStorageOnly=0 +StandardEject=1 +Interface=0x00 +NeedResponse=0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 new file mode 100755 index 0000000..d7e8196 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0146 @@ -0,0 +1,4 @@ +# ZTE MF652 (Variant) +TargetVendor=0x19d2 +TargetProductList="0142,0143" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 new file mode 100755 index 0000000..0b06b0f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0149 @@ -0,0 +1,5 @@ +# ZTE MF190 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 new file mode 100755 index 0000000..0b7cd3b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0150 @@ -0,0 +1,4 @@ +# ZTE MF656A, MF668A, MF669 +TargetVendor=0x19d2 +TargetProduct=0x0124 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 new file mode 100755 index 0000000..7fb3c05 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0154 @@ -0,0 +1,4 @@ +# ZTE MF190 (Variant) and others +TargetVendor=0x19d2 +TargetProductList="0017,0117,2003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 new file mode 100755 index 0000000..8e4414f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0166 @@ -0,0 +1,4 @@ +# ZTE MF820 4G LTE +TargetVendor=0x19d2 +TargetProduct=0x0167 +MessageContent="55534243123456782400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 new file mode 100755 index 0000000..4aac36c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0169 @@ -0,0 +1,4 @@ +# ZTE A371B +TargetVendor=0x19d2 +TargetProduct=0x0170 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 new file mode 100755 index 0000000..c12e299 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0198 @@ -0,0 +1,4 @@ +# ZTE MF820s, MF832s +TargetVendor=0x19d2 +TargetProduct=0x0199 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 new file mode 100755 index 0000000..ed2082f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0266 @@ -0,0 +1,5 @@ +# Onda MT8205 LTE +TargetVendor=0x19d2 +TargetProduct=0x0265 +StandardEject=1 +MessageContent="55534243d8a523862400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 new file mode 100755 index 0000000..f93dccd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0304 @@ -0,0 +1,4 @@ +# ZTE MF821D (Variant) +TargetVendor=0x19d2 +TargetProduct=0x0349 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 new file mode 100755 index 0000000..c5bb6e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0318 @@ -0,0 +1,4 @@ +# ZTE MF821D/MF826 +TargetVendor=0x19d2 +TargetProductList="0317,0330" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 new file mode 100755 index 0000000..3c23ebd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0325 @@ -0,0 +1,4 @@ +# ZTE MF821D +TargetVendor=0x19d2 +TargetProduct=0x0326 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 new file mode 100755 index 0000000..f7a6966 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0388 @@ -0,0 +1,4 @@ +# ZTE MF90 Mobile Hotspot +TargetVendor=0x19d2 +TargetProduct=0x0447 +MessageContent="55534243123456782400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 new file mode 100755 index 0000000..3cf0cca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_0413 @@ -0,0 +1,4 @@ +# Telewell TW-LTE 4G +TargetVendor=0x19d2 +TargetProduct=0x0412 +MessageContent="55534243d8a523862400000080000685000000240000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 new file mode 100755 index 0000000..2d66c17 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1001 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3805-Z +TargetVendor=0x19d2 +TargetProductList="1002,1003" +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 new file mode 100755 index 0000000..61a7f71 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1007 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K3570-Z +TargetVendor=0x19d2 +TargetProduct=0x1008 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 new file mode 100755 index 0000000..878fcdd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1009 @@ -0,0 +1,4 @@ +# Vodafone (ZTE) K3571-Z +TargetVendor=0x19d2 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 new file mode 100755 index 0000000..58f33cb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1013 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3806-Z +TargetVendor=0x19d2 +TargetProduct=0x1015 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 new file mode 100755 index 0000000..667e00a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1017 @@ -0,0 +1,4 @@ +# Vodafone K5006Z (MF821) +TargetVendor=0x19d2 +TargetProduct=0x1018 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 new file mode 100755 index 0000000..ef133ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1019 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R203 Router +TargetVendor=0x19d2 +TargetProduct=0x1021 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 new file mode 100755 index 0000000..ef133ca --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1020 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R203 Router +TargetVendor=0x19d2 +TargetProduct=0x1021 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 new file mode 100755 index 0000000..de52f8c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1022 @@ -0,0 +1,4 @@ +# Vodafone / ZTE K4201-z +TargetVendor=0x19d2 +TargetProductList="1023,1024" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 new file mode 100755 index 0000000..a6762cc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1026 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R212 Router +TargetVendor=0x19d2 +TargetProductList="1027,1028,1029" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 new file mode 100755 index 0000000..a00acd1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1030 @@ -0,0 +1,4 @@ +# Vodafone K5008-z (MF823) +TargetVendor=0x19d2 +TargetProductList="1031,1032" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 new file mode 100755 index 0000000..03372d1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1034 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R206-z Router +TargetVendor=0x19d2 +TargetProductList="1035,1036,1037" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 new file mode 100755 index 0000000..aac2900 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1038 @@ -0,0 +1,4 @@ +# ZTE / Vodafone K4607-Z +TargetVendor=0x19d2 +TargetProductList="1039,1040" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 new file mode 100755 index 0000000..878b3fc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1042 @@ -0,0 +1,4 @@ +# Vodafone / ZTE R209-z Router +TargetVendor=0x19d2 +TargetProduct=0x1043 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 new file mode 100755 index 0000000..ebf0d0e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1046 @@ -0,0 +1,4 @@ +# ZTE MF730 +TargetVendor=0x19d2 +TargetProduct=0x1047 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 new file mode 100755 index 0000000..4c722c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1171 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K4510-Z +TargetVendor=0x19d2 +TargetProduct=0x1173 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 new file mode 100755 index 0000000..61ef605 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1175 @@ -0,0 +1,6 @@ +# Vodafone / ZTE K3770-Z +TargetVendor=0x19d2 +TargetProduct=0x1177 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 new file mode 100755 index 0000000..086ade9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1179 @@ -0,0 +1,6 @@ +# Vodafone (ZTE) K3772-Z +TargetVendor=0x19d2 +TargetProduct=0x1181 +StandardEject=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 new file mode 100755 index 0000000..052d473 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1201 @@ -0,0 +1,4 @@ +# ZTE MF691 (T-Mobile Rocket 2.0) +TargetVendor=0x19d2 +TargetProduct=0x1203 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 new file mode 100755 index 0000000..f7e1e50d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1207 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1208 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 new file mode 100755 index 0000000..ef7946c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1210 @@ -0,0 +1,4 @@ +# ZTE MF195 +TargetVendor=0x19d2 +TargetProduct=0x1211 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 new file mode 100755 index 0000000..2634bc1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1216 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1217 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 new file mode 100755 index 0000000..f75da93 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1219 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProductList="1220,1222" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 new file mode 100755 index 0000000..baa492f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1224 @@ -0,0 +1,4 @@ +# ZTE MF190 +TargetVendor=0x19d2 +TargetProduct=0x0082 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 new file mode 100755 index 0000000..90b32f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1225 @@ -0,0 +1,4 @@ +# ZTE MF668 (Variant), MF70 +TargetVendor=0x19d2 +TargetProduct=0x1405 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 new file mode 100755 index 0000000..3ed950f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1227 @@ -0,0 +1,4 @@ +# ZTE MF680 +TargetVendor=0x19d2 +TargetProduct=0x1252 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 new file mode 100755 index 0000000..086af2c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1232 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProductList="1268,2003" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 new file mode 100755 index 0000000..ac2c702 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1233 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProduct=0x1270 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 new file mode 100755 index 0000000..5b4def7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1237 @@ -0,0 +1,4 @@ +# ZTE / Vodafone K4201 +TargetVendor=0x19d2 +TargetProduct=0x0017 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 new file mode 100755 index 0000000..ff575e6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1238 @@ -0,0 +1,4 @@ +# ZTE MF825A +TargetVendor=0x19d2 +TargetProduct=0x0017 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 new file mode 100755 index 0000000..a5d5af4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1420 @@ -0,0 +1,4 @@ +# ZTE MF730 +TargetVendor=0x19d2 +TargetProduct=0x1405 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 new file mode 100755 index 0000000..469143b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1511 @@ -0,0 +1,4 @@ +# ZTE MFxxx +TargetVendor=0x19d2 +TargetProduct=0x1512 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 new file mode 100755 index 0000000..7f08f33 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1514 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1515 +MessageContent="5553424348c4758600000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 new file mode 100755 index 0000000..8a7450e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1517 @@ -0,0 +1,4 @@ +# ZTE MF192 (Variant) +TargetVendor=0x19d2 +TargetProduct=0x1519 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 new file mode 100755 index 0000000..06c58c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1520 @@ -0,0 +1,4 @@ +# ZTE MF652 +TargetVendor=0x19d2 +TargetProduct=0x0142 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 new file mode 100755 index 0000000..2a16858 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1523 @@ -0,0 +1,4 @@ +# ZTE MF591 TMobile +TargetVendor=0x19d2 +TargetProduct=0x1525 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 new file mode 100755 index 0000000..25e78c0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1528 @@ -0,0 +1,4 @@ +# ZTE MF196 +TargetVendor=0x19d2 +TargetProduct=0x1527 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 new file mode 100755 index 0000000..b3617a6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1536 @@ -0,0 +1,4 @@ +# ZTE MF190J +TargetVendor=0x19d2 +TargetProductList="1537,1538" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 new file mode 100755 index 0000000..60b06eb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1542 @@ -0,0 +1,4 @@ +# ZTE MF190J +TargetVendor=0x19d2 +TargetProduct=0x1544 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 new file mode 100755 index 0000000..5b99ce8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1580 @@ -0,0 +1,4 @@ +# ZTE MF195E +TargetVendor= 0x19d2 +TargetProduct=0x1582 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 new file mode 100755 index 0000000..2cbf979 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1588 @@ -0,0 +1,5 @@ +# ZTE MF710M Variants +TargetVendor= 0x19d2 +TargetProductList="1589,1591,1592" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 new file mode 100755 index 0000000..13cc530 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_1595 @@ -0,0 +1,5 @@ +# ZTE MF710 (Vietnam) a.o. +TargetVendor= 0x19d2 +TargetProductList="1592,1596,1600" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 new file mode 100755 index 0000000..067173e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2000 @@ -0,0 +1,5 @@ +# ZTE devices, some Onda devices +TargetVendor= 0x19d2 +TargetProductList="0001,0002,0015,0016,0017,0019,0024,0031,0033,0037,0042,0052,0055,0061,0063,0064,0066,0091,0108,0117,0128,0151,0157,0177,1402,2002,2003" +StandardEject=1 +MessageContent="55534243123456702000000080000c85010101180101010101000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 new file mode 100755 index 0000000..5d97b1e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_2004 @@ -0,0 +1,4 @@ +# ZTE MF60 +TargetVendor=0x19d2 +TargetProduct=0x1402 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd new file mode 100755 index 0000000..dd47bee --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_bccd @@ -0,0 +1,6 @@ +# ZTE AX226 WiMax +TargetVendor=0x19d2 +TargetProduct=0x0172 +MessageContent="555342431234567824000000800006bc626563240000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde new file mode 100755 index 0000000..1beb1df --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffde @@ -0,0 +1,4 @@ +# ZTE AC682 (a.k.a. SmartFren Connex) +TargetVendor=0x19d2 +TargetProduct=0xffdd +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 new file mode 100755 index 0000000..e0b6d26 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_ffe6 @@ -0,0 +1,4 @@ +# ZTE "ffe" devices 1 (e.g. Cricket A605) +TargetVendor=0x19d2 +TargetProduct=0xffe5 +MessageContent="5553424330f4cf8124000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 new file mode 100755 index 0000000..1fa9350 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff5 @@ -0,0 +1,4 @@ +# ZTE "ff" devices 1 +TargetVendor=0x19d2 +TargetProductList="ffe4,ffe9,fff1,fffe,ffff" +MessageContent="5553424312345678c00000008000069f030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 new file mode 100755 index 0000000..e894e96 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/19d2_fff6 @@ -0,0 +1,4 @@ +# ZTE "fff" devices 2 +TargetVendor=0x19d2 +TargetProduct=0xfff1 +MessageContent="5553424312345678c00000008000069f030000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 new file mode 100755 index 0000000..3580f54 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_1000 @@ -0,0 +1,6 @@ +# BandRich BandLuxe C100, C120, C170, C270, C3xx, C508 +TargetVendor=0x1a8d +TargetProductList="1002,1007,1009,100d,2006" +StandardEject=1 +ReleaseDelay=4000 +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 new file mode 100755 index 0000000..16d85c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1a8d_2000 @@ -0,0 +1,4 @@ +# BandRich BandLuxe C339 +TargetVendor=0x1a8d +TargetProduct=0x2006 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 new file mode 100755 index 0000000..983903a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ab7_5700 @@ -0,0 +1,4 @@ +# Hummer DTM5731, Aircard 901 +TargetVendor=0x1ab7 +TargetProductList="2000,5731" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 new file mode 100755 index 0000000..f357fcc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1b7d_0700 @@ -0,0 +1,4 @@ +# EpiValley SEC-7089 (featured by Alegro and Starcomms / iZAP) +TargetVendor=0x1b7d +TargetProduct=0x0001 +MessageContent="555342431234567824000000800008FF05B112AEE102000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f new file mode 100755 index 0000000..c618dce --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_000f @@ -0,0 +1,4 @@ +# ETCOM E300 +TargetVendor=0x1bbb +TargetProduct=0x000f +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca new file mode 100755 index 0000000..df5753b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_00ca @@ -0,0 +1,3 @@ +# Alcatel OT-X080C +TargetClass=0xff +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f new file mode 100755 index 0000000..97f7a3a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_011f @@ -0,0 +1,4 @@ +# Haier EVDO Rev. A +TargetVendor=0x1bbb +TargetProduct=0x0106 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c new file mode 100755 index 0000000..46e4105 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_022c @@ -0,0 +1,2 @@ +# Alcatel X602D +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e new file mode 100755 index 0000000..717aa47 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_025e @@ -0,0 +1,4 @@ +# Yota 4G LTE W8 +TargetVendor=0x1bbb +TargetProduct=0x0195 +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 new file mode 100755 index 0000000..bd30b57 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f000 @@ -0,0 +1,4 @@ +# Alcatel X200/X200L/X060S/L100V, Archos G9 3G Key +TargetVendor=0x1bbb +TargetProductList="0000,0017,00b7,011e,0191,0195" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 new file mode 100755 index 0000000..d68767d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f017 @@ -0,0 +1,4 @@ +# Alcatel OT-X220D, L100V +TargetVendor=0x1bbb +TargetProductList="0017,011e,0203" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 new file mode 100755 index 0000000..11262b0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1bbb_f052 @@ -0,0 +1,4 @@ +# Alcatel OT X220L +TargetVendor=0x1bbb +TargetProduct=0x0052 +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 new file mode 100755 index 0000000..d43b947 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_1001 @@ -0,0 +1,4 @@ +# Alcatel One Touch X020 +TargetVendor=0x1c9e +TargetProductList="6060,6061" +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 new file mode 100755 index 0000000..77cb169 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6000 @@ -0,0 +1,5 @@ +# TU930, IVIO IV-2010u +TargetClass=0xff +MessageContent="55534243123456780000000000000601000000000000000000000000000000" + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage new file mode 100755 index 0000000..3d6d53d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_6061_uPr=Storage @@ -0,0 +1,3 @@ +# Vibe 3G Modem +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 new file mode 100755 index 0000000..ed42e10 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9101 @@ -0,0 +1,4 @@ +# Emobile D12LC +TargetVendor=0x1c9e +TargetProduct=0x9104 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 new file mode 100755 index 0000000..d0a1e1d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9200 @@ -0,0 +1,4 @@ +# MyWave SW006 Sport Phone/Modem Combination +TargetVendor=0x1c9e +TargetProduct=0x9202 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 new file mode 100755 index 0000000..e02d00d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9401 @@ -0,0 +1,4 @@ +# Emobile D21LC +TargetVendor=0x1c9e +TargetProduct=0x9404 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 new file mode 100755 index 0000000..ef03cd9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9800 @@ -0,0 +1,3 @@ +# Longcheer SU9800 +TargetClass=0xff +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff new file mode 100755 index 0000000..80a3146 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_98ff @@ -0,0 +1,4 @@ +# Telewell TW-3G HSPA+, FS01BU 3G, SmartBro WM66E +TargetVendor=0x1c9e +TargetProductList="6801,9801,9803" +MessageContent="55534243123456780000000080000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe new file mode 100755 index 0000000..25767f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9bfe @@ -0,0 +1,4 @@ +# XS Stick W100 (Omega) +TargetVendor=0x1c9e +TargetProduct=0x9b01 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 new file mode 100755 index 0000000..f8bbedd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9d00 @@ -0,0 +1,3 @@ +# Prolink PCM100 +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 new file mode 100755 index 0000000..3a03904 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e00 @@ -0,0 +1,3 @@ +# BSNL Capitel +TargetClass=0xff +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 new file mode 100755 index 0000000..e90fd46 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_9e08 @@ -0,0 +1,6 @@ +# Explay Slim +TargetVendor=0x1c9e +TargetProduct=0x9e18 +SierraMode=1 + + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 new file mode 100755 index 0000000..a5b7a8e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000 @@ -0,0 +1,5 @@ +# Longcheer/Longsoon (aka Omega Technology) devices +TargetVendor=0x1c9e +TargetProductList="9000,9603,9605,9607,9900" +MessageContent="555342431234567800000000000001ff000000000000000000000000000000" +WaitBefore=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem new file mode 100755 index 0000000..a645abc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f000_uMa=USB_Modem @@ -0,0 +1,5 @@ +# MobiData MBD-200HU and others +TargetVendor=0x1c9e +TargetProductList="9000,9603,9605,9607,9900,9a00" +MessageContent="55534243123456788000000080000606f50402527000000000000000000000" +WaitBefore=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 new file mode 100755 index 0000000..d1d007b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1c9e_f010 @@ -0,0 +1,4 @@ +# Micromax MMX400R / 4G Systems XSBOXGO +TargetVendor=0x1c9e +TargetProduct=0xf101 +MessageContent="55534243123456780000000000000606f50402527000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 new file mode 100755 index 0000000..62675f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1000 @@ -0,0 +1,4 @@ +# TechFaith BSNL Capitel +TargetVendor=0x1d09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 new file mode 100755 index 0000000..3af3048 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1021 @@ -0,0 +1,4 @@ +# Aiko 81D +TargetVendor=0x1d09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 new file mode 100755 index 0000000..eb9133c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1d09_1025 @@ -0,0 +1,4 @@ +# TechFaith FlyingLARK46 +TargetVendor=0x1d09 +TargetProduct=0x1026 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 new file mode 100755 index 0000000..8cb08ae --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1da5_f000 @@ -0,0 +1,4 @@ +# Qisda H21 Flying Beetle +TargetVendor=0x1da5 +TargetProduct=0x4512 +QisdaMode=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 new file mode 100755 index 0000000..c137caa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dbc_0669 @@ -0,0 +1,2 @@ +# Wisue W340 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 new file mode 100755 index 0000000..2ad5e61 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1dd6_1000 @@ -0,0 +1,5 @@ +# Solomon S3Gm-660 +TargetVendor=0x1dd6 +TargetProduct=0x1002 +MessageContent="55534243123456781200000080000603000000020000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 new file mode 100755 index 0000000..92145ba --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1de1_1101 @@ -0,0 +1,4 @@ +# Philips PicoPix 1020 Projector +TargetVendor=0x21e7 +TargetProduct=0x000e +MessageContent="55534243123456780000000000000cff020000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 new file mode 100755 index 0000000..04931f9 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e0e_f000 @@ -0,0 +1,5 @@ +# Option iCON 210, PROLiNK PHS100 + PH300, Hyundai MB-810, A-Link 3GU +TargetVendor=0x1e0e +TargetProductList="9000,9100,9200" +MessageContent="555342431234567800000000000006bd000000020000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 new file mode 100755 index 0000000..db6a46d --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1e89_f000 @@ -0,0 +1,4 @@ +# 3GO 3GO11 HSUPA +TargetVendor=0x1e89 +TargetProduct=0x1a20 +MessageContent="5553424312345678800000008000060619181a207000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 new file mode 100755 index 0000000..eb04ecd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1edf_6003 @@ -0,0 +1,2 @@ +# AirPlus MCD-800 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 new file mode 100755 index 0000000..a292e64 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0003 @@ -0,0 +1,5 @@ +# Onda MV815U +TargetVendor=0x1ee8 +TargetProduct=0x0004 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 new file mode 100755 index 0000000..9a9fbaa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0007 @@ -0,0 +1,4 @@ +# Onda POM1051 +TargetVendor=0x1ee8 +TargetProduct=0x000b +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 new file mode 100755 index 0000000..7b7f881 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0009 @@ -0,0 +1,5 @@ +# Onda MW833UP +TargetVendor=0x1ee8 +TargetProduct=0x000b +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 new file mode 100755 index 0000000..4fc5320 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0013 @@ -0,0 +1,5 @@ +# Onda MW833UP + MW835UP +TargetVendor=0x1ee8 +TargetProductList="0011,0012,0014" +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 new file mode 100755 index 0000000..d50cde6 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0018 @@ -0,0 +1,5 @@ +# Onda MO835UP +TargetVendor=0x1ee8 +TargetProduct=0x0017 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 new file mode 100755 index 0000000..251f807 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0040 @@ -0,0 +1,5 @@ +# Onda MW836UP-K +TargetVendor=0x1ee8 +TargetProductList="003e,003f" +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 new file mode 100755 index 0000000..92b567f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0045 @@ -0,0 +1,5 @@ +# Onda MDC655 +TargetVendor=0x1ee8 +TargetProduct=0x0044 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 new file mode 100755 index 0000000..a0618ab --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0048 @@ -0,0 +1,4 @@ +# Onda MT655 +TargetVendor=0x1ee8 +TargetProduct=0x0049 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a new file mode 100755 index 0000000..97dd71b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004a @@ -0,0 +1,4 @@ +# Onda MDC655 +TargetVendor=0x1ee8 +TargetProduct=0x0049 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f new file mode 100755 index 0000000..e81eb29 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_004f @@ -0,0 +1,5 @@ +# Onda MDC655 Variant +TargetVendor=0x1ee8 +TargetProduct=0x004e +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 new file mode 100755 index 0000000..8638639 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0054 @@ -0,0 +1,5 @@ +# Onda MW875UP +TargetVendor=0x1ee8 +TargetProduct=0x0053 +MessageContent="555342431234567800000000000010ff000000000000000000000000000000" +NeedResponse=1 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 new file mode 100755 index 0000000..985e4a3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0060 @@ -0,0 +1,4 @@ +# Onda MSA 14.4 (TIM Brasil) +TargetVendor=0x1ee8 +TargetProduct=0x005f +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 new file mode 100755 index 0000000..b46c775 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0063 @@ -0,0 +1,4 @@ +# Onda TM201, CM201 +TargetVendor=0x1ee8 +TargetProductList="0064,0065" +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 new file mode 100755 index 0000000..da73ac1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1ee8_0068 @@ -0,0 +1,4 @@ +# Onda WM301 +TargetVendor=0x1ee8 +TargetProduct=0x0069 +MessageContent="555342431234567800000000000008ff000000000000030000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 new file mode 100755 index 0000000..162c20b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1f28_0021 @@ -0,0 +1,4 @@ +# Cricket A600 +TargetVendor=0x1f28 +TargetProduct=0x0020 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 new file mode 100755 index 0000000..2eabd0a --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0032 @@ -0,0 +1,2 @@ +# Franklin Wireless U210 (Variant) +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 new file mode 100755 index 0000000..100ce55 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0130 @@ -0,0 +1,4 @@ +# Franklin Wireless U210 +TargetVendor=0x1fac +TargetProduct=0x0131 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 new file mode 100755 index 0000000..e04b132 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0150 @@ -0,0 +1,4 @@ +# Franklin Wireless U600 +TargetVendor=0x1fac +TargetProduct=0x0151 +MessageContent="555342431234567824000000800108df200000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 new file mode 100755 index 0000000..9db4de7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/1fac_0151 @@ -0,0 +1,2 @@ +# Franklin Wireless U600 +Configuration=2 \ No newline at end of file diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 new file mode 100755 index 0000000..6362dad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_00a6 @@ -0,0 +1,4 @@ +# D-Link DWM-157 B1 +TargetVendor=0x2001 +TargetProduct=0x7d02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 new file mode 100755 index 0000000..b1fe1f7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_7600 @@ -0,0 +1,2 @@ +# D-Link DWM-157 C1 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff new file mode 100755 index 0000000..383e0c7 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_98ff @@ -0,0 +1,5 @@ +# D-Link DWM-221 +TargetVendor=0x2001 +TargetProduct=0x7e16 +MessageContent="55534243f8d2e6838000000080000606f50402527000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 new file mode 100755 index 0000000..8d4e874 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a401 @@ -0,0 +1,4 @@ +# D-Link DWM-221 B1 +TargetVendor=0x2001 +TargetProduct=0x7e19 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 new file mode 100755 index 0000000..d6c4893 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a403 @@ -0,0 +1,4 @@ +# D-Link DWM-156 A8, DWP-157 B1 +TargetVendor=0x2001 +TargetProductList="7d0b,7d0c" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 new file mode 100755 index 0000000..3208b3b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a405 @@ -0,0 +1,4 @@ +# D-Link DWM-167 A1 +TargetVendor=0x2001 +TargetProduct=0x7d0d +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 new file mode 100755 index 0000000..4148807 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a406 @@ -0,0 +1,4 @@ +# D-Link DWM-221 +TargetVendor=0x2001 +TargetProduct=0x7e19 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 new file mode 100755 index 0000000..6522888 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a407 @@ -0,0 +1,4 @@ +# D-Link DWM-157 C1 +TargetVendor=0x2001 +TargetProduct=0x7d0e +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a new file mode 100755 index 0000000..3db2e55 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40a @@ -0,0 +1,4 @@ +# D-Link DWM-156 A8 (Myanmar) +TargetVendor=0x2001 +TargetProduct=0x7d10 +MessageContent="555342431234567800000000000003f0010100000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d new file mode 100755 index 0000000..4f12646 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a40d @@ -0,0 +1,4 @@ +# D-Link DWR-910 +TargetVendor=0x2001 +TargetProduct=0x7e38 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 new file mode 100755 index 0000000..1b4ee3e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a706 @@ -0,0 +1,4 @@ +# D-Link DWM-156 A7 +TargetVendor=0x2001 +TargetProduct=0x7d01 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 new file mode 100755 index 0000000..6362dad --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a707 @@ -0,0 +1,4 @@ +# D-Link DWM-157 B1 +TargetVendor=0x2001 +TargetProduct=0x7d02 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 new file mode 100755 index 0000000..15c8323 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a708 @@ -0,0 +1,4 @@ +# D-Link DWM-158 D1 +TargetVendor=0x2001 +TargetProduct=0x7d03 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 new file mode 100755 index 0000000..97e0c7b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a805 @@ -0,0 +1,4 @@ +# D-Link DWR-510 +TargetVendor=0x2001 +TargetProduct=0x7e12 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b new file mode 100755 index 0000000..fbbb6c8 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2001_a80b @@ -0,0 +1,5 @@ +# D-Link DWM-156 (Variant) +TargetVendor=0x2001 +TargetProduct=0x7d00 +MessageContent="555342431234567800000000000003f0010100000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 new file mode 100755 index 0000000..02a559f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2015_0001 @@ -0,0 +1,3 @@ +# Venus VT-18 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 new file mode 100755 index 0000000..98fe5a4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_1023 @@ -0,0 +1,6 @@ +# Haier CE682 (EVDO) +TargetVendor=0x201e +TargetProduct=0x1022 +MessageContent="55534243123456780000000000000600000000000000000000000000000000" +MessageContent2="5553424312345679c000000080000671030000000000000000000000000000" +NeedResponse=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 new file mode 100755 index 0000000..84fefe1 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/201e_2009 @@ -0,0 +1,3 @@ +# Haier CE 100 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 new file mode 100755 index 0000000..f67f7a2 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_0002 @@ -0,0 +1,4 @@ +# Mediatek MT6229, Micromax MMX 377G, Olicard 300 +TargetVendor=0x2020 +TargetProductList="2000,4000,4010" +MessageContent="555342430820298900000000000003f0010100000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e new file mode 100755 index 0000000..ec38550 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00e @@ -0,0 +1,5 @@ +# SpeedUp SU-8000 and others +TargetVendor=0x2020 +TargetProductList="1005,1008" +StandardEject=1 +WaitBefore=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f new file mode 100755 index 0000000..64e60f0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2020_f00f @@ -0,0 +1,5 @@ +# SpeedUp SU-8000U +TargetVendor=0x2020 +TargetProduct=0x1005 +StandardEject=1 +WaitBefore=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 new file mode 100755 index 0000000..8bac36b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_1000 @@ -0,0 +1,4 @@ +# Changhong CH690, D-Link DWM-163 + DWM-168 +TargetVendor=0x2077 +TargetProductList="7001,7010,7011" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 new file mode 100755 index 0000000..e65c97b --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2077_f000 @@ -0,0 +1,5 @@ +# Telenet 3G dongle (T&W WU160), Netgear AC327U and others +TargetVendor=0x2077 +TargetProductList="9000,9062,a000,a003" +StandardEject=1 +MessageContent="55534243123456700000000000000616aa0000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a new file mode 100755 index 0000000..9e20b7e --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00a @@ -0,0 +1,4 @@ +# BM WM78 +TargetVendor=0x20a6 +TargetProduct=0x1000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e new file mode 100755 index 0000000..dd6aefa --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20a6_f00e @@ -0,0 +1,4 @@ +# Intex 3.5G +TargetVendor=0x20a6 +TargetProduct=0x1105 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 new file mode 100755 index 0000000..a65c1ea --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/20b9_1682 @@ -0,0 +1,3 @@ +# Tlaytech TEU800 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 new file mode 100755 index 0000000..ebb13da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_1000 @@ -0,0 +1,4 @@ +# StrongRising (China Telcom), Air FlexiNet +TargetVendor=0x21f5 +TargetProduct=0x2008 +MessageContent="5553424312345678c000000080000671010000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 new file mode 100755 index 0000000..ef2c097 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/21f5_3010 @@ -0,0 +1,4 @@ +# StrongRising STD808 +TargetVendor=0x21f5 +TargetProduct=0x1101 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 new file mode 100755 index 0000000..4339910 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2262_0001 @@ -0,0 +1,4 @@ +# Viettel VT100 +TargetVendor=0x2262 +TargetProduct=0x0002 +MessageContent="5553424340799288C000000080010A16000000C00000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 new file mode 100755 index 0000000..a610b60 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6801 @@ -0,0 +1,3 @@ +# WeTelecom WM-D200 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 new file mode 100755 index 0000000..55b59c5 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22de_6803 @@ -0,0 +1,4 @@ +# WeTelecom WM-D300 +TargetVendor=0x22de +TargetProduct=0x6801 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 new file mode 100755 index 0000000..7980f66 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/22f4_0021 @@ -0,0 +1,3 @@ +# Tata Photon+, Olive VME102 +TargetClass=0xff +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 new file mode 100755 index 0000000..5008f5c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0001 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 (BSNL Teracom) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 new file mode 100755 index 0000000..5008f5c --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0003 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 (BSNL Teracom) +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 new file mode 100755 index 0000000..63996da --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0007 @@ -0,0 +1,2 @@ +# Visiontek 82GH 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b new file mode 100755 index 0000000..e8dd4bb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000b @@ -0,0 +1,2 @@ +# Zoom 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c new file mode 100755 index 0000000..e8dd4bb --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000c @@ -0,0 +1,2 @@ +# Zoom 3G +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d new file mode 100755 index 0000000..66ec4cc --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_000d @@ -0,0 +1,2 @@ +# Intex Speed 3G v7.2 +Configuration=3 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 new file mode 100755 index 0000000..721e5c4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0101 @@ -0,0 +1,2 @@ +# Linktop LW272/LW273 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 new file mode 100755 index 0000000..e543736 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/230d_0103 @@ -0,0 +1,2 @@ +# Teracom LW272 +Configuration=2 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 new file mode 100755 index 0000000..6251747 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_0200 @@ -0,0 +1,4 @@ +# TP-Link MA180 +TargetVendor=0x2357 +TargetProduct=0x0201 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 new file mode 100755 index 0000000..aba6b49 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/2357_f000 @@ -0,0 +1,4 @@ +# TP-Link MA260 +TargetVendor=0x2357 +TargetProduct=0x9000 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 new file mode 100755 index 0000000..95cee31 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/23a2_1010 @@ -0,0 +1,4 @@ +# Titan 3.5G +TargetVendor=0x23a2 +TargetProduct=0x1234 +MessageContent="555342431234567800000000000006161f6d62706b00000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_a000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_b000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_c000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 new file mode 100755 index 0000000..6981490 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/257a_d000 @@ -0,0 +1,4 @@ +# Unknown devices +TargetVendor=0x257a +TargetProductList="1601,161f,162f,261f,262f,361f,362f" +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 new file mode 100755 index 0000000..e9d346f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/6000_1000 @@ -0,0 +1,4 @@ +# BlueLink BL-EV08C +TargetVendor=0x05c6 +TargetProduct=0x6000 +MessageContent="5553424312345678c000000080000671010000000000000000000000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 new file mode 100755 index 0000000..85b2776 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/8888_6500 @@ -0,0 +1,4 @@ +# Exiss Mobile E-190 series (made by C-motech) +TargetVendor=0x16d8 +TargetProduct=0x6533 +MessageContent="5553424398e2c4812400000080000bff524445564348473d43440000000000" diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 new file mode 100755 index 0000000..d23a846 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.d/ed09_1021 @@ -0,0 +1,4 @@ +# Aiko 81D, fw with wrong vendor ID +TargetVendor=0xed09 +TargetProduct=0x1010 +StandardEject=1 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.h b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.h new file mode 100755 index 0000000..f40796f --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.h @@ -0,0 +1,116 @@ +/* + This file is part of usb_modeswitch, a mode switching tool for controlling + the mode of 'multi-state' USB devices + + Version 2.4.0, 2016/06/12 + Copyright (C) 2007 - 2016 Josua Dietze + + Config file parsing stuff borrowed from Guillaume Dargaud + (http://www.gdargaud.net/Hack/SourceCode.html) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details: + + http://www.gnu.org/licenses/gpl.txt + +*/ + +#include <stdlib.h> +#include <libusb.h> + +void readConfigFile(const char *configFilename); +void printConfig(); +int switchSendMessage(); +int switchConfiguration(); +int switchAltSetting(); +void switchHuaweiMode(); + +void switchSierraMode(); +void switchGCTMode(); +void switchKobilMode(); +void switchQisdaMode(); +void switchQuantaMode(); +void switchSequansMode(); +void switchActionMode(); +void switchBlackberryMode(); +void switchPantechMode(); +void switchCiscoMode(); +int switchSonyMode(); +int detachDriver(); +int checkSuccess(); +int sendMessage(char* message, int count); +int write_bulk(int endpoint, unsigned char *message, int length); +int read_bulk(int endpoint, unsigned char *buffer, int length); +void release_usb_device(int dummy); +struct libusb_device* search_devices( int *numFound, int vendor, char* productList, + int targetClass, int configuration, int mode); +int find_first_bulk_endpoint(int direction); +int get_current_config_value(); +int get_interface_class(); +char* ReadParseParam(const char* FileName, char *VariableName); +int hex2num(char c); +int hex2byte(const char *hex); +int hexstr2bin(const char *hex, unsigned char *buffer, int len); +void printVersion(); +void printHelp(); +void close_all(); +void abortExit(); +int readArguments(int argc, char **argv); +void deviceDescription(); +void resetUSB(); +void release_usb_device(int dummy); +int findMBIMConfig(int vendor, int product, int mode); + + +// Boolean +#define and && +#define or || +#define not ! + +// Bitwise +#define bitand & +#define bitor | +#define compl ~ +#define xor ^ + +// Equals +#define and_eq &= +#define not_eq != +#define or_eq |= +#define xor_eq ^= + +extern char* ReadParseParam(const char* FileName, char *VariableName); + +extern char *TempPP; + +#define ParseParamString(ParamFileName, Str) \ + if ((TempPP=ReadParseParam((ParamFileName), #Str))!=NULL) \ + strcpy(Str, TempPP); else Str[0]='\0' + +#define ParseParamInt(ParamFileName, Int) \ + if ((TempPP=ReadParseParam((ParamFileName), #Int))!=NULL) \ + Int=atoi(TempPP) + +#define ParseParamHex(ParamFileName, Int) \ + if ((TempPP=ReadParseParam((ParamFileName), #Int))!=NULL) \ + Int=strtol(TempPP, NULL, 16) + +#define ParseParamFloat(ParamFileName, Flt) \ + if ((TempPP=ReadParseParam((ParamFileName), #Flt))!=NULL) \ + Flt=atof(TempPP) + +#define ParseParamBool(ParamFileName, B) \ + if ((TempPP=ReadParseParam((ParamFileName), #B))!=NULL) \ + B=(toupper(TempPP[0])=='Y' || toupper(TempPP[0])=='T'|| TempPP[0]=='1'); else B=0 + +#define ParseParamBoolMap(ParamFileName, B, M, Const) \ + if ((TempPP=ReadParseParam((ParamFileName), #B))!=NULL) \ + if (toupper(TempPP[0])=='Y' || toupper(TempPP[0])=='T'|| TempPP[0]=='1') \ + M=M+Const diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh new file mode 100755 index 0000000..b126ec3 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# part of usb_modeswitch 2.4.0 +device_in() +{ + if [ ! -e /var/lib/usb_modeswitch/$1 ]; then + return 0 + fi + while read line + do + if [ $(expr "$line" : "$2:$3") != 0 ]; then + return 1 + fi + done </var/lib/usb_modeswitch/$1 + if [ $(expr "$line" : "$2:$3") != 0 ]; then + return 1 + fi + return 0 +} + +if [ $(expr "$1" : "--.*") ]; then + p_id=$4 + if [ -z $p_id ]; then + prod=$5 + if [ -z $prod ]; then + prod=$3 + fi + prod=${prod%/*} + v_id=0x${prod%/*} + p_id=0x${prod#*/} + if [ "$v_id" = "0x" ]; then + v_id="0" + p_id="0" + fi + v_id="$(printf %04x $(($v_id)))" + p_id="$(printf %04x $(($p_id)))" + else + v_id=$3 + fi +fi +PATH=/sbin:/usr/sbin:$PATH +case "$1" in + --driver-bind) + # driver binding code removed + exit 0 + ;; + --symlink-name) + device_in "link_list" $v_id $p_id + if [ "$?" = "1" ]; then + if [ -e "/usr/sbin/usb_modeswitch_dispatcher" ]; then + exec usb_modeswitch_dispatcher $1 $2 2>>/dev/null + fi + fi + exit 0 + ;; +esac + +IFS='/' read -r p1 p2 <<EOF +$1 +EOF + +PATH=/bin:/sbin:/usr/bin:/usr/sbin +init_path=`readlink /sbin/init` +if [ `basename $init_path` = "systemd" ]; then + systemctl --no-block start usb_modeswitch@$p1'_'$p2.service +elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then + initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1 +else + # only old distros, new udev will kill all subprocesses + exec 1<&- 2<&- 5<&- 7<&- + exec usb_modeswitch_dispatcher --switch-mode $1 & +fi +exit 0 diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl new file mode 100755 index 0000000..3e590fd --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch.tcl @@ -0,0 +1,1015 @@ +#!/usr/bin/tclsh + +# Wrapper (tcl) for usb_modeswitch, called from +# /lib/udev/rules.d/40-usb_modeswitch.rules +# (part of data pack "usb-modeswitch-data") via +# /lib/udev/usb_modeswitch +# +# Does ID check on newly discovered USB devices and calls +# the mode switching program with the matching parameter +# file from /usr/share/usb_modeswitch +# +# Part of usb-modeswitch-2.4.0 package +# (C) Josua Dietze 2009-2016 + +set arg0 [lindex $argv 0] +if [regexp {\.tcl$} $arg0] { + if [file exists $arg0] { + set argv [lrange $argv 1 end] + source $arg0 + exit + } +} + +# Setting of these switches is done in the global config +# file (/etc/usb_modeswitch.conf) if available + +set flags(logging) 1 +set flags(noswitching) 0 +set flags(stordelay) 0 +set flags(logwrite) 0 +# also settable in device config files +set flags(nombim) 0 + +# Execution starts at file bottom + +proc {Main} {argv argc} { + +global scsi usb config match device flags setup devdir loginit + +set flags(config) "" +Log "[ParseGlobalConfig]" + +# The facility to add a symbolic link pointing to the +# ttyUSB port which provides interrupt transfer, i.e. +# the port to connect through. +# Will check for interrupt endpoint in ttyUSB port (lowest if +# there is more than one); if found, return "gsmmodem[n]" name +# to udev for symlink creation + +# This is run once for every port of LISTED devices by +# a udev rule + +if {[lindex $argv 0] == "--symlink-name"} { + puts -nonewline [SymLinkName [lindex $argv 1]] + SafeExit +} + +if {[lindex $argv 0] == "--switch-systemd"} { + set argList [split [lindex $argv 1] _] + Log "\nStarted via systemd" +} else { + if {[lindex $argv 0] == "--switch-upstart"} { + Log "\nStarted via upstart" + } + set argList [split [lindex $argv 1] /] +} +if [string length [lindex $argList 1]] { + set device [lindex $argList 1] +} else { + set device "noname" +} +if {$flags(stordelay) > 0} { + SetStorageDelay $flags(stordelay) +} + +Log "Raw args from udev: [lindex $argv 1]\n" + +if {$device == "noname"} { + Log "\nNo data from udev. Exit" + SafeExit +} + +if {![regexp -- {--switch-} [lindex $argv 0]]} { + Log "\nNo command given. Exit" + SafeExit +} + +set setup(dbdir) /usr/share/usb_modeswitch +set setup(dbdir_etc) /etc/usb_modeswitch.d + + +if {![file exists $setup(dbdir)] && ![file exists $setup(dbdir_etc)]} { + Log "\nError: no config database found in /usr/share or /etc. Exit" + SafeExit +} +set bindir /usr/sbin + +set devList1 {} +set devList2 {} + + +# arg 0: the bus id for the device (udev: %b), often ommitted +# arg 1: the "kernel name" for the device (udev: %k) +# +# Used to determine the top directory for the device in sysfs + +set ifChk 0 +if {[string length [lindex $argList 0]] == 0} { + if {[string length [lindex $argList 1]] == 0} { + Log "No device number values given from udev! Exit" + SafeExit + } else { + if {![regexp {(.*?):} [lindex $argList 1] d dev_top]} { + if {![regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top]} { + Log "Could not determine device dir from udev values! Exit" + SafeExit + } + } + } +} else { + set dev_top [lindex $argList 0] + regexp {(.*?):} $dev_top d dev_top +} + +set devdir /sys/bus/usb/devices/$dev_top +if {![file isdirectory $devdir]} { + Log "Top device directory not found ($devdir)! Exit" + SafeExit +} +Log "Use top device dir $devdir" + +set iface 0 +Log "Check class of first interface ..." +set config(class) [IfClass 0 $devdir] +if {$config(class) < 0} { + Log " No access to interface 0. Exit" + SafeExit +} +Log " Interface 0 class is $config(class)." + +set ifdir [file tail [IfDir $iface $devdir]] +regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface + +set flags(logwrite) 1 + +# Mapping of the short string identifiers (in the config +# file names) to the long name used here +# +# If we need them it's a snap to add new attributes here! + +set match(sVe) scsi(vendor) +set match(sMo) scsi(model) +set match(sRe) scsi(rev) +set match(uMa) usb(manufacturer) +set match(uPr) usb(product) +set match(uSe) usb(serial) + + +# Now reading the USB attributes +if {![ReadUSBAttrs $devdir]} { + Log "USB attributes not found in sysfs tree. Exit" + SafeExit +} +set config(vendor) $usb(idVendor) +set config(product) $usb(idProduct) + + +if $flags(logging) { + Log "\n----------------\nUSB values from sysfs:" + foreach attr {manufacturer product serial} { + Log " $attr\t$usb($attr)" + } + Log "----------------" +} + +if $flags(noswitching) { + SysLog "usb_modeswitch: switching disabled, no action for $usb(idVendor):$usb(idProduct)" + Log "\nSwitching globally disabled. Exit" + SafeExit +} + +if {$usb(bNumConfigurations) == "1"} { + set configParam "-u -1" + Log "bNumConfigurations is 1 - don't check for active configuration" +} else { + set configParam "" +} + +# Check (and switch) for operating system if Huawei device present + +set flags(os) "linux" +if {$usb(idVendor) == "12d1" && [regexp -nocase {android} [exec cat /proc/version]]} { + set flags(os) "android" +} +if {$flags(os) == "android"} { + set configList [ConfigGet conflist $usb(idVendor):#android] +} else { + set configList [ConfigGet conflist $usb(idVendor):$usb(idProduct)] +} + +if {[llength $configList] == 0} { + Log "Aargh! Config file missing for $usb(idVendor):$usb(idProduct)! Exit" + SafeExit +} +Log "ConfigList: $configList" + +# Check if there is more than one config file for this USB ID, +# which would make an attribute test necessary. If so, check if +# SCSI values are needed + +set scsiNeeded 0 +if {[llength $configList] > 1} { + if [regexp {:s} $configList] { + set scsiNeeded 1 + } +} +if $scsiNeeded { + if [ReadSCSIAttrs $devdir:$iface] { + Log "----------------\nSCSI values from sysfs:" + foreach attr {vendor model rev} { + Log " $attr\t$scsi($attr)" + } + Log "----------------" + } else { + Log "Could not get SCSI attributes, exclude devices with SCSI match" + } +} else { + Log "SCSI attributes not needed, move on" +} + +# General wait - some devices need this +after 500 + +# Now check for a matching config file. Matching is done +# by MatchDevice + +set report {} +foreach mconfig $configList { + + # skipping installer leftovers like "*.rpmnew" + if [regexp {\.(dpkg|rpm)} $mconfig] {continue} + + Log "Check config: $mconfig" + if [MatchDevice $mconfig] { + Log "! matched. Read config data" +# set flags(config) $mconfig + if [string length $usb(busnum)] { + set busParam "-b [string trimleft $usb(busnum) 0]" + set devParam "-g [string trimleft $usb(devnum) 0]" + } else { + set busParam "" + set devParam "" + } + set flags(config) [ConfigGet conffile $mconfig] + ParseDeviceConfig $flags(config) + if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] { + Log "Note: Using generic manufacturer configuration for \"$flags(os)\"" + } + if $flags(nombim) { + set config(NoMBIMCheck) 1 + } + if {$config(WaitBefore) != ""} { + Log "Delay time of $config(WaitBefore) seconds" + append config(WaitBefore) "000" + after $config(WaitBefore) + Log " wait is over, start mode switch" + } + if {$config(NoMBIMCheck)==0 && $usb(bNumConfigurations) > 1} { + Log "Device may have an MBIM configuration, check driver ..." + if [CheckMBIM] { + Log " driver for MBIM devices is available" + Log "Find MBIM configuration number ..." + if [catch {set cfgno [exec /usr/sbin/usb_modeswitch -j -Q $busParam $devParam -v $usb(idVendor) -p $usb(idProduct)]} err] { + Log "Error when trying to find MBIM configuration, switch to legacy modem mode" + } else { + set cfgno [string trim $cfgno] + if {$cfgno > 0} { + set config(Configuration) $cfgno + set flags(config) "Configuration=$cfgno" + } else { + Log " No MBIM configuration found, switch to legacy modem mode" + } + } + } else { + Log " no MBIM driver found, switch to legacy modem mode" + } + } + if [PantechAutoSwitch] { + Log "Waiting for Pantech auto-modeswitch" + set report "ok:busdev" + break + } + if {$config(Configuration) == 0} { + Log "Config file contains dummy method, do nothing. Exit" + SafeExit + } + UnbindDriver $devdir $ifdir + # Now we are actually switching + if $flags(logging) { + Log "Command to be run:\nusb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$flags(config)" + set report [exec /usr/sbin/usb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1] + Log "\nVerbose debug output of usb_modeswitch and libusb follows" + Log "(Note that some USB errors are to be expected in the process)" + Log "--------------------------------" + Log $report + Log "--------------------------------" + Log "(end of usb_modeswitch output)\n" + } else { + set report [exec /usr/sbin/usb_modeswitch -Q -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1] + } + break + } else { + Log "* no match, don't use this config" + } +} + +# Switching is complete; success checking was either +# done by usb_modeswitch and logged via syslog OR bus/dev +# parameter were used; then we do check for success HERE + +if {$config(Configuration) != ""} { + set ifdir [regsub {(\d):\d+\.0} $ifdir "\\1:$config(Configuration).0"] +} + +if [regexp {ok:busdev} $report] { + if [CheckSuccess $devdir] { + Log "Mode switching was successful, found $usb(idVendor):$usb(idProduct) ($usb(manufacturer): $usb(product))" + SysLog "usb_modeswitch: switched to $usb(idVendor):$usb(idProduct) on [format %03d $usb(busnum)]/[format %03d $usb(devnum)]" + } else { + Log "\nTarget config not matching - current values are" + LogAttributes + Log "\nMode switching may have failed. Exit" + SafeExit + } +} else { + if {![file isdirectory $devdir]} { + Log "Device directory in sysfs is gone! Something went wrong, abort" + SafeExit + } + if {![regexp {ok:} $report]} { + Log "\nCore program reported switching failure. Exit" + SafeExit + } + # Give the device another second if it's not fully back yet + if {![file exists $devdir/idProduct]} { + after 1000 + } + ReadUSBAttrs $devdir $ifdir +} + +# driver binding removed !! + +if {[string length "$usb(idVendor)$usb(idProduct)"] < 8} { + if {![regexp {ok:(\w{4}):(\w{4})} $report d usb(idVendor) usb(idProduct)]} { + Log "No target vendor/product ID found or given, can't continue. Abort" + SafeExit + } +} +# wait for drivers to bind +after 500 +if {[llength [glob -nocomplain $devdir/$ifdir/ttyUSB*]] > 0} { + Log "Serial USB driver bound to interface 0\n will try to guess and symlink modem port on next connect" + AddToList link_list $usb(idVendor):$usb(idProduct) +} + +# In newer kernels there is a switch to avoid the use of a device +# reset (e.g. from usb-storage) which would possibly switch back +# a mode-switching device to initial mode +if [regexp {ok:} $report] { + Log "Check for AVOID_RESET_QUIRK kernel attribute" + if [file exists $devdir/avoid_reset_quirk] { + if [catch {exec echo "1" >$devdir/avoid_reset_quirk 2>/dev/null} err] { + Log " Error setting the attribute: $err" + } else { + Log " AVOID_RESET_QUIRK activated" + } + } else { + Log " not present in this kernel" + } +} + +Log "\nAll done, exit\n" +SafeExit + +} +# end of proc {Main} + + +proc {ReadSCSIAttrs} {topdir} { + +global scsi +set counter 0 +set sysdir $topdir +Log "Check storage tree in sysfs ..." +while {$counter < 20} { + Log " loop $counter/20" + if {![file isdirectory $sysdir]} { + # Device is gone. Unplugged? Switched by kernel? + Log " sysfs device tree is gone; abort SCSI value check" + return 0 + } + # Searching the storage/SCSI tree; might take a while + if {[set dirList [glob -nocomplain $topdir/host*]] != ""} { + set sysdir [lindex $dirList 0] + if {[set dirList [glob -nocomplain $sysdir/target*]] != ""} { + set sysdir [lindex $dirList 0] + regexp {.*target(.*)} $sysdir d subdir + if {[set dirList [glob -nocomplain $sysdir/$subdir*]] != ""} { + set sysdir [lindex $dirList 0] + if [file exists $sysdir/vendor] { + Log " Storage tree is ready" + break + } + } + } + } + after 500 + incr counter +} +if {$counter == 20} { + Log "SCSI tree not found; you may want to check if this path/file exists:" + Log "$sysdir/vendor\n" + return 0 +} + +Log "Read SCSI values ..." +foreach attr {vendor model rev} { + if [file exists $sysdir/$attr] { + set rc [open $sysdir/$attr r] + set scsi($attr) [read -nonewline $rc] + close $rc + } else { + set scsi($attr) "" + Log "Warning: SCSI attribute \"$attr\" not found." + } +} +return 1 + +} +# end of proc {ReadSCSIAttrs} + + +proc {ReadUSBAttrs} {dir args} { + +global usb + +set attrList {idVendor idProduct bConfigurationValue manufacturer product serial devnum busnum bNumConfigurations} +set mandatoryList {idVendor idProduct bNumConfigurations} +set result 1 +if {$args != ""} { + lappend attrList "$args/bInterfaceClass" + lappend mandatoryList "$args/bInterfaceClass" +} +foreach attr $attrList { + if [file exists $dir/$attr] { + set rc [open $dir/$attr r] + set usb($attr) [string trim [read -nonewline $rc]] + close $rc + } else { + set usb($attr) "" + if {[lsearch $mandatoryList $attr] > -1} { + set result 0 + } + if {$attr == "serial"} {continue} + Log " Warning: USB attribute \"$attr\" not found" + } +} +return $result + +} +# end of proc {ReadUSBAttrs} + + +proc {MatchDevice} {config} { + +global scsi usb match + +set devinfo [file tail $config] +set infoList [split $devinfo :] +set stringList [lrange $infoList 2 end] +if {[llength $stringList] == 0} {return 1} + +foreach teststring $stringList { + if {$teststring == "?"} {return 0} + set tokenList [split $teststring =] + set id [lindex $tokenList 0] + set matchstring [lindex $tokenList 1] + set blankstring "" + regsub -all {_} $matchstring { } blankstring + Log "match $match($id)" + Log " string1 (exact): $matchstring" + Log " string2 (blanks): $blankstring" + Log " device string: [set $match($id)]" + if {!([string match *$matchstring* [set $match($id)]] || [string match *$blankstring* [set $match($id)]])} { + return 0 + } +} +return 1 + +} +# end of proc {MatchDevice} + + +proc {ParseGlobalConfig} {} { + +global flags +set configFile "" +set places [list /etc/usb_modeswitch.conf /etc/sysconfig/usb_modeswitch /etc/default/usb_modeswitch] +foreach cfg $places { + if [file exists $cfg] { + set configFile $cfg + break + } +} +if {$configFile == ""} {return} + +set rc [open $configFile r] +while {![eof $rc]} { + gets $rc line + if [regexp {^#} [string trim $line]] {continue} + if [regexp {DisableMBIMGlobal\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(nombim) 1 + } else { + set flags(nombim) 0 + } + } + if [regexp {DisableSwitching\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(noswitching) 1 + } + } + if [regexp {EnableLogging\s*=\s*([^\s]+)} $line d val] { + if [regexp -nocase {1|yes|true} $val] { + set flags(logging) 1 + } else { + set flags(logging) 0 + } + } + if [regexp {SetStorageDelay\s*=\s*([^\s]+)} $line d val] { + if [regexp {\d+} $val] { + set flags(stordelay) $val + } + } + +} +return "Use global config file: $configFile" + +} +# end of proc {ParseGlobalConfig} + + +proc ParseDeviceConfig {cfg} { + +global config +set config(WaitBefore) "" +set config(TargetVendor) "" +set config(TargetProduct) "" +set config(TargetClass) "" +set config(Configuration) "" +set config(NoMBIMCheck) 0 +set config(PantechMode) 0 +set config(CheckSuccess) 20 + +foreach pname [lsort [array names config]] { + if [regexp -line "^\[^# \]*?$pname.*?= *(0x(\\w+)|\"(\[0-9a-fA-F,\]+)\"|(\[0-9\]+)) *\$" $cfg d config($pname)] { +# Log "config: $pname set to $config($pname)" + } +} + +set config(WaitBefore) [string trimleft $config(WaitBefore) 0] + +} +# end of proc {ParseDeviceConfig} + + +proc ConfigGet {command config} { + +global setup usb flags + +switch $command { + + conflist { + # Unpackaged configs first; sorting is essential for priority + set configList [lsort -decreasing [glob -nocomplain $setup(dbdir_etc)/$config*]] + set configList [concat $configList [lsort -decreasing [glob -nocomplain $setup(dbdir)/$config*]]] + eval lappend configList [glob -nocomplain $setup(dbdir)/$usb(idVendor):#$flags(os)] + if [file exists $setup(dbdir)/configPack.tar.gz] { + Log "Found packed config collection $setup(dbdir)/configPack.tar.gz" + if [catch {set packedList [exec tar -tzf $setup(dbdir)/configPack.tar.gz 2>/dev/null]} err] { + Log "Error: problem opening config package; tar returned\n $err" + return {} + } + set packedList [split $packedList \n] + set packedConfigList [lsort -decreasing [lsearch -glob -all -inline $packedList $config*]] + lappend packedConfigList [lsearch -inline $packedList $usb(idVendor):#$flags(os)] + # Now add packaged configs with a mark, again sorted for priority + foreach packedConfig $packedConfigList { + lappend configList "pack/$packedConfig" + } + } + return $configList + } + conffile { + if [regexp {^pack/} $config] { + set config [regsub {pack/} $config {}] + Log "Extract config $config from collection $setup(dbdir)/configPack.tar.gz" + set configContent [exec tar -xzOf $setup(dbdir)/configPack.tar.gz $config 2>/dev/null] + } else { + if [regexp [list $setup(dbdir_etc)] $config] { + Log "Use config file from override folder $setup(dbdir_etc)" + SysLog "usb_modeswitch: use overriding config file $config; make sure this is intended" + SysLog "usb_modeswitch: please report any new or corrected settings; otherwise, check for outdated files" + } + set rc [open $config r] + set configContent [read $rc] + close $rc + } + return $configContent + } +} + +} +# end of proc {ConfigGet} + +proc {Log} {msg} { + +global flags device loginit + +if {$flags(logging) == 0} {return} + +if $flags(logwrite) { + if [string length $loginit] { + exec echo "\nUSB_ModeSwitch log from [clock format [clock seconds]]" >/var/log/usb_modeswitch_$device + exec echo "$loginit" >>/var/log/usb_modeswitch_$device + set loginit "" + } + exec echo $msg >>/var/log/usb_modeswitch_$device +} else { + append loginit "\n$msg" +} + +} +# end of proc {Log} + + +# Writing the log file and exit +proc {SafeExit} {} { + +global flags +set flags(logwrite) 1 +Log "" +exit + +} +# end of proc {SafeExit} + + +proc {SymLinkName} {path} { +global device flags + +proc {hasInterrupt} {ifDir} { + if {[llength [glob -nocomplain $ifDir/ttyUSB*]] == 0} { + Log " no ttyUSB interface - skip endpoint check" + return 0 + } + foreach epDir [glob -nocomplain $ifDir/ep_*] { + set e [file tail $epDir] + Log " check $e ..." + if [file exists $epDir/type] { + set rc [open $epDir/type r] + set type [read $rc] + close $rc + if [regexp {Interrupt} $type] { + Log " $e has interrupt transfer type" + return 1 + } + } + } + return 0 +} + +set loginit "usb_modeswitch called with --symlink-name\n parameter: $path\n" + +# In case the device path is returned as /class/tty/ttyUSB, +# get the USB device path from linked tree "device" +set linkpath /sys$path/device +if [file exists $linkpath] { + if {[file type $linkpath] == "link"} { + set rawpath [file readlink $linkpath] + set trimpath [regsub -all {\.\./} $rawpath {}] + if [file isdirectory /sys/$trimpath] { + append loginit "\n Use path $path\n" + set path /$trimpath + } + } +} +if {![regexp {([0-9]+-[0-9]+[\.0-9]*:[^/]*).*(ttyUSB[0-9]+)} $path d myDev myPort]} { + if $flags(logging) { + set device [clock clicks] + set flags(logwrite) 1 + Log "$loginit\nThis is not a ttyUSB port. Abort" + } + return "" +} + +set device ttyUSB_$myDev +set flags(logwrite) 1 +Log "$loginit\nMy name is $myPort\n" + +if {![regexp {(.*?[0-9]+)\.([0-9]+)/ttyUSB} /sys$path d ifRoot ifNum]} { + Log "Could not find interface in path\n $path. Abort" + return "" +} + +set ifDir $ifRoot.$ifNum + +Log "Check my endpoints ...\n in $ifDir" +if [hasInterrupt $ifDir] { + Log "\n--> I am an interrupt port" + set rightPort 1 +} else { + Log "\n--> I am not an interrupt port\n" + set rightPort 0 +} + +# There are devices with more than one interrupt interface. +# Assume that the lowest of these is usable. Check all +# possible lower interfaces + +if { $rightPort && ($ifNum > 0) } { + Log "\nLook for lower ports with interrupt endpoints" + for {set i 0} {$i < $ifNum} {incr i} { + set ifDir $ifRoot.$i + Log " in ifDir $ifDir ..." + if [hasInterrupt $ifDir] { + Log "\n--> found an interrupt interface below me\n" + set rightPort 0 + break + } + } +} +if {$rightPort == 0} { + Log "Return empty name and exit" + return "" +} + +Log "\n--> No interrupt interface below me\n" + +cd /dev +set idx 2 +set symlinkName "gsmmodem" +while {$idx < 256} { + if {![file exists $symlinkName]} { + set placeholder [open /dev/$symlinkName w] + close $placeholder + break + } + set symlinkName gsmmodem$idx + incr idx +} +if {$idx == 256} {return ""} + +Log "Return symlink name \"$symlinkName\" and exit" +return $symlinkName + +} +# end of proc {SymLinkName} + + +# Add USB ID to list of devices needing later treatment +proc {AddToList} {name id} { + +set listfile /var/lib/usb_modeswitch/$name +if [file exists $listfile] { + set rc [open $listfile r] + set buffer [read $rc] + close $rc + if [string match *$id* $buffer] { + return + } + set idList [split [string trim $buffer] \n] +} +lappend idList $id +set buffer [join $idList "\n"] +if [catch {set lc [open $listfile w]}] {return} +puts $lc $buffer +close $lc + +} +# end of proc {AddToList} + + +proc {CheckSuccess} {devdir} { + +global config usb flags + +# For Cisco AM10, target device not on same port +if {$usb(idVendor) == "1307" && $usb(idProduct) == "1169"} { + set devdir [string range $devdir 0 end-1]2 +} +set ifdir [file tail [IfDir 0 $devdir]] +if {[string length $config(TargetClass)] || [string length $config(Configuration)]} { + set config(TargetVendor) $usb(idVendor) + set config(TargetProduct) $usb(idProduct) +} +Log "Check success of mode switch for max. $config(CheckSuccess) seconds ..." + +set expected 1 +for {set i 1} {$i <= $config(CheckSuccess)} {incr i} { + after 1000 + if {![file isdirectory $devdir]} { + Log " Wait for device file system ($i sec.) ..." + continue + } else { + Log " Read attributes ..." + } + set ifdir [IfDir 0 $devdir] + if {$ifdir == ""} {continue} + set ifdir [file tail $ifdir] + if {![ReadUSBAttrs $devdir $ifdir]} { + Log " Essential attributes are missing, continue wait ..." + continue + } + if [string length $config(Configuration)] { + if {$usb(bConfigurationValue) != $config(Configuration)} {continue} + } + if [string length $config(TargetClass)] { + if {![regexp $usb($ifdir/bInterfaceClass) $config(TargetClass)]} { + if {$config(class) != $usb($ifdir/bInterfaceClass} { + set expected 0 + } else {continue} + } + } + if {![regexp $usb(idVendor) $config(TargetVendor)]} { + if {![regexp $usb(idVendor) $config(vendor)]} { + set expected 0 + } else {continue} + } + if {![regexp $usb(idProduct) $config(TargetProduct)]} { + if {![regexp $usb(idProduct) $config(product)]} { + set expected 0 + } else {continue} + } + # Arriving here means that device attributes have changed + if $expected { + Log " All attributes matched" + } else { + if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] { + Log " idProduct has changed after generic mode-switch, assume success" + } else { + Log " Attributes are different but target values are unexpected:" + LogAttributes + } + } + break +} +if {$i > 20} {return 0} else {return 1} + +} +# end of proc {CheckSuccess} + + +proc {IfDir} {iface devdir} { + +set allfiles [glob -nocomplain $devdir/*] +set files [glob -nocomplain $devdir/*.$iface] +if {[llength $files] == 0} { + return "" +} +set ifdir [lindex $files 0] +if {![file isdirectory $ifdir]} { + return "" +} +return $ifdir + +} +# end of proc {IfDir} + +proc {IfClass} {iface devdir} { + +set ifdir [IfDir $iface $devdir] + +if {![file exists $ifdir/bInterfaceClass]} { + return -1 +} +set rc [open $ifdir/bInterfaceClass r] +set c [read $rc] +close $rc +return [string trim $c] + +} +# end of proc {IfClass} + + +proc {SysLog} {msg} { + +global flags +if {![info exists flags(logger)]} { + set flags(logger) "" + foreach fn {/bin/logger /usr/bin/logger} { + if [file exists $fn] { + set flags(logger) $fn + } + } + Log "Logger is $flags(logger)" +} +if {$flags(logger) == ""} { + Log "Can't add system message, no syslog helper found" + return +} +catch {exec $flags(logger) -p syslog.notice "$msg" 2>/dev/null} + +} +# end of proc {SysLog} + +proc {SetStorageDelay} {secs} { + +Log "Adjust delay for USB storage devices ..." +set attrib /sys/module/usb_storage/parameters/delay_use +if {![file exists $attrib]} { + Log "Error: could not find delay_use attribute" + return +} +if [catch {set ch [open $attrib r+]} err] { + Log "Error: could not access delay_use attribute: $err" + return +} +if {[read $ch] < $secs} { + seek $ch 0 start + puts -nonewline $ch $secs + Log " Delay set to $secs seconds\n" +} else { + Log " Current value is higher than $secs. Leave it alone\n" +} +close $ch + +} +# end of proc {SetStorageDelay} + +proc {CheckMBIM} {} { + +set kversion [exec uname -r] +if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/cdc_mbim*]] {return 1} +if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1} +return 0 + +} + +proc {CheckQMI} {} { + +set kversion [exec uname -r] +if [llength [glob -nocomplain /lib/modules/$kversion/kernel/drivers/net/usb/qmi_wwan*]] {return 1} +if [file exists /sys/bus/usb/drivers/cdc_mbim] {return 1} +return 0 + +} + +proc {PantechAutoSwitch} {} { + +global config flags +if {$config(PantechMode) == 3} {return 1} +if {$config(PantechMode) == 1} { + if {"$config(vendor):$config(product)" == "10a9:6080"} { + set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=2"] + Log " PantechMode changed to 2" + return 0 + } elseif [CheckQMI] { + set flags(config) [regsub {PantechMode *= *1} $flags(config) "PantechMode=4"] + Log " PantechMode changed to 4" + return 0 + } else { + return 1 + } +} else {return 0} + +} + +proc UnbindDriver {devdir ifdir} { + +set att $devdir/$ifdir/driver/unbind +if [file exists $att] { + Log "Unbinding driver" + exec echo -n "$ifdir" > $att +} + +} + +proc {LogAttributes} {} { + +global flags usb +if $flags(logging) { + set attrList {idVendor idProduct bConfigurationValue manufacturer product serial} + foreach attr [lsort [array names usb]] { + Log " [format %-26s $attr:] $usb($attr)" + } +} + +} + +proc {HasFF} {devdir} { + +set i 0 +while {[set dir [IfDir $i $devdir]] != ""} { + set c [exec cat $dir/bInterfaceClass] + if {$c == "ff"} {return 1} + incr i +} +return 0 + +} + + +# The actual entry point +Main $argv $argc diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service new file mode 100755 index 0000000..91e5ac0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service @@ -0,0 +1,8 @@ +[Unit] +Description=USB_ModeSwitch_%i + +[Service] +Type=oneshot +ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %i +#ExecStart=/bin/echo %i + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 new file mode 100755 index 0000000..5b826d4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 @@ -0,0 +1,21 @@ +.TH "USB_MODESWITCH_DISPATCHER" "1" +.SH "NAME" +usb_modeswitch_dispatcher - Linux wrapper for usb_modeswitch (not intended for direct invocation) +.SH "SYNOPSIS" +.PP +\fBusb_modeswitch_dispatcher\fR +.SH "DESCRIPTION" +.PP +usb_modeswitch_dispatcher will do detailed device checking and will subsequently +use the Linux-independent usb_modeswitch binary together with the selected device +config file to switch the mode of certain USB devices. +.PP +If no drivers are taking care of the device after the mode switch, the dispatcher +will try to load and bind the "option" serial driver to any USB interfaces with +class 0xff, in order to make the device useable in case it is not recognized by that +driver yet. This may or may not work. +.PP +This program is called by udev and is not supposed to be called directly +by the user. +.SH SEE ALSO +.BR usb_modeswitch(1). diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service new file mode 100755 index 0000000..91e5ac0 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch@.service @@ -0,0 +1,8 @@ +[Unit] +Description=USB_ModeSwitch_%i + +[Service] +Type=oneshot +ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %i +#ExecStart=/bin/echo %i + diff --git a/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 new file mode 100755 index 0000000..5b826d4 --- /dev/null +++ b/android/external/usb_modeswitch/usb_modeswitch/usb_modeswitch_dispatcher.1 @@ -0,0 +1,21 @@ +.TH "USB_MODESWITCH_DISPATCHER" "1" +.SH "NAME" +usb_modeswitch_dispatcher - Linux wrapper for usb_modeswitch (not intended for direct invocation) +.SH "SYNOPSIS" +.PP +\fBusb_modeswitch_dispatcher\fR +.SH "DESCRIPTION" +.PP +usb_modeswitch_dispatcher will do detailed device checking and will subsequently +use the Linux-independent usb_modeswitch binary together with the selected device +config file to switch the mode of certain USB devices. +.PP +If no drivers are taking care of the device after the mode switch, the dispatcher +will try to load and bind the "option" serial driver to any USB interfaces with +class 0xff, in order to make the device useable in case it is not recognized by that +driver yet. This may or may not work. +.PP +This program is called by udev and is not supposed to be called directly +by the user. +.SH SEE ALSO +.BR usb_modeswitch(1). diff --git a/android/hardware/ril/libril/Android.mk b/android/hardware/ril/libril/Android.mk index e5f7104..b79d4c7 100755 --- a/android/hardware/ril/libril/Android.mk +++ b/android/hardware/ril/libril/Android.mk @@ -5,6 +5,9 @@ LOCAL_VENDOR_MODULE := true +LOCAL_POST_INSTALL_CMD := \ + cp -ravf vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an10.so $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/libril.so + LOCAL_SRC_FILES:= \ ril.cpp \ ril_event.cpp\ diff --git a/android/hardware/ril/rild/Android.mk b/android/hardware/ril/rild/Android.mk index b8ba508..1b3d5bf 100755 --- a/android/hardware/ril/rild/Android.mk +++ b/android/hardware/ril/rild/Android.mk @@ -29,7 +29,7 @@ LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE:= rild -LOCAL_VINTF_FRAGMENTS := radio.xml +#LOCAL_VINTF_FRAGMENTS := radio.xml ifeq ($(PRODUCT_COMPATIBLE_PROPERTY),true) LOCAL_INIT_RC := rild.rc LOCAL_CFLAGS += -DPRODUCT_COMPATIBLE_PROPERTY diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/Android.mk b/android/vendor/aw/public/prebuild/lib/librild/libquecte/Android.mk new file mode 100755 index 0000000..f421803 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/Android.mk @@ -0,0 +1,43 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libreference-ril-an12 + +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES + +ifeq ($(TARGET_ARCH), arm64) + LOCAL_SRC_FILES := lib64/libreference-ril-an12.so +else + LOCAL_SRC_FILES := lib32/libreference-ril-an12.so +endif + +LOCAL_VENDOR_MODULE := true +LOCAL_CHECK_ELF_FILES := false + +include $(BUILD_PREBUILT) + + +include $(CLEAR_VARS) + +LOCAL_MODULE := libreference-ril-an10 + +LOCAL_MODULE_SUFFIX := .so +LOCAL_MODULE_CLASS := SHARED_LIBRARIES + +# ifeq ($(TARGET_ARCH), arm64) +# LOCAL_SRC_FILES := lib64/libreference-ril-an10.so +# else +# LOCAL_SRC_FILES := lib32/libreference-ril-an10.so +# endif + +LOCAL_SRC_FILES_32 := lib32/libreference-ril-an10.so +LOCAL_SRC_FILES_64 := lib64/libreference-ril-an10.so + +LOCAL_VENDOR_MODULE := true +LOCAL_CHECK_ELF_FILES := false + +include $(BUILD_PREBUILT) + + diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an10.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an10.so new file mode 100755 index 0000000..76ccc0d --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an10.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an12.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an12.so new file mode 100755 index 0000000..dd5697e --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-an12.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-ndk.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-ndk.so new file mode 100755 index 0000000..3ddb73f --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libreference-ril-ndk.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an10.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an10.so new file mode 100755 index 0000000..4f3e4fa --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an10.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an12.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an12.so new file mode 100755 index 0000000..8b4ac2d --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib32/libril-an12.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an10.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an10.so new file mode 100755 index 0000000..2b51ac6 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an10.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an12.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an12.so new file mode 100755 index 0000000..4ed32d1 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-an12.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-ndk.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-ndk.so new file mode 100755 index 0000000..5f13078 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libreference-ril-ndk.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an10.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an10.so new file mode 100755 index 0000000..9b58791 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an10.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an12.so b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an12.so new file mode 100755 index 0000000..5f07421 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/libquecte/lib64/libril-an12.so Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/apns-full-conf.xml b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/apns-full-conf.xml new file mode 100755 index 0000000..5718e10a --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/apns-full-conf.xml @@ -0,0 +1,35501 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- +/* +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<!-- use empty string to specify no proxy or port --> +<!-- This version must agree with that in apps/common/res/apns.xml --> +<apns version="8"> + + <apn carrier="AT&T PHONE TEST SIM" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="phone" + user="" + password="" + proxy="" + port="" + mmsc="http://mmsc.mobile.att.net" + mmsproxy="proxy.mobile.att.net" + mmsport="80" + type="default,mms,supl,hipri,fota,dun" + mtu="1410" + /> + + <apn carrier="T-Mobile TEST SIM" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="phone" + user="" + password="" + proxy="" + port="" + type="default,supl,hipri,dun" + mtu="1440" + /> + + <apn carrier="U.S.Cellular TEST SIM" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="usccinternet" + user="" + password="" + proxy="" + port="" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,hipri,dun,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mtu="1422" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test FOTA" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test CBS" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test IMS" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + authtype="3" + bearer_bitmask="6" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test Internet" + carrier_id = "1911" + mcc="001" + mnc="01" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test FOTA" + mcc="001" + mnc="010" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Test CBS" + mcc="001" + mnc="010" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test IMS" + mcc="001" + mnc="010" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test IMS" + mcc="001" + mnc="010" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + mcc="001" + mnc="010" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + authtype="3" + bearer_bitmask="6" + /> + + <apn carrier="Test Internet" + mcc="001" + mnc="010" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + mcc="001" + mnc="010" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Cosmote Wireless Internet" + carrier_id = "747" + mcc="202" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="Cosmote Wireless Internet" + carrier_id = "747" + mcc="202" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cosmote Mms" + carrier_id = "747" + mcc="202" + mnc="01" + apn="mms" + mmsc="http://mmsc.cosmote.gr:8002" + mmsproxy="10.10.10.20" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vf Mobile Internet" + carrier_id = "2399" + mcc="202" + mnc="05" + apn="" + type="ia" + /> + + <apn carrier="Vf Mobile Internet" + carrier_id = "2399" + mcc="202" + mnc="05" + apn="internet.vodafone.gr" + type="default,supl" + /> + + <apn carrier="Vf MMS" + carrier_id = "2399" + mcc="202" + mnc="05" + apn="mms.vodafone.net" + user="user" + password="pass" + mmsc="http://mms.vodafone.gr" + mmsproxy="213.249.19.49" + mmsport="5080" + authtype="1" + type="mms" + /> + + <apn carrier="Q Internet" + carrier_id = "749" + mcc="202" + mnc="09" + apn="myq" + type="default,supl" + /> + + <apn carrier="Q-Telecom MMS GPRS" + carrier_id = "749" + mcc="202" + mnc="09" + apn="q-mms.myq.gr" + mmsc="http://mms.myq.gr" + mmsproxy="192.168.80.134" + mmsport="8080" + type="mms" + /> + + <apn carrier="Wind Internet" + carrier_id = "1519" + mcc="202" + mnc="10" + apn="gint.b-online.gr" + type="default,supl" + /> + + <apn carrier="Wind MMS" + carrier_id = "1519" + mcc="202" + mnc="10" + apn="mnet.b-online.gr" + mmsc="http://192.168.200.95/servlets/mms" + mmsproxy="192.168.200.11" + mmsport="9401" + type="mms" + /> + + <apn carrier="Tele2 GPRS" + carrier_id = "1643" + mcc="204" + mnc="02" + apn="internet.tele2.nl" + mmsc="http://mmsc.tele2.nl" + mmsproxy="193.12.40.64" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="MVNO NL" + carrier_id = "2149" + mcc="204" + mnc="03" + apn="internet.mvno.mobi" + user="mvno" + password="mvno" + authtype="1" + type="default,supl" + mvno_match_data="20403" + mvno_type="imsi" + /> + + <apn carrier="MVNO NL" + carrier_id = "2149" + mcc="204" + mnc="03" + apn="ims" + protocol="IPV4" + type="ims" + mvno_match_data="20403" + mvno_type="imsi" + /> + + <apn carrier="Jump Roam" + carrier_id = "2138" + mcc="204" + mnc="04" + apn="mobiledata" + authtype="0" + mvno_type="spn" + mvno_match_data="Jump" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="204" + mnc="04" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="547275554B3030656E" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="204" + mnc="04" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="54727555533030656E" + /> + + <apn carrier="Vodafone NL" + mcc="204" + mnc="04" + apn="live.vodafone.com" + user="vodafone" + password="vodafone" + authtype="1" + mmsc="http://mmsc.mms.vodafone.nl" + mmsproxy="192.168.251.150" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="EHRPD - VZW Roaming Internet" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWINTERNET" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="LTE - VZW Roaming Internet" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWINTERNET" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="EHRPD - VZW Roaming FOTA" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="LTE - VZW Roaming FOTA" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="LTE - VZW Roaming IMS" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="IMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="EHRPD - VZW Roaming IMS" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="IMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="LTE - VZW Roaming CBS" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWAPP" + type="cbs,mms" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="EHRPD - VZW Roaming CBS" + carrier_id = "1839" + mcc="204" + mnc="04" + apn="VZWAPP" + type="cbs,mms" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mvno_type="gid" + mvno_match_data="BAE0000000000000" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="CSpire international" + carrier_id = "1836" + mcc="204" + mnc="04" + apn="internet.cs4glte.com" + server="*" + user="Uniroam@inet.cs.com" + password="cs3g" + authtype ="3" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + mvno_type="spn" + mvno_match_data="C Spire" + type="default,internet,mms" + protocol="IPV4V6" + /> + + <apn carrier="CSpire international" + carrier_id = "1836" + mcc="204" + mnc="04" + apn="admin.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + mvno_type="spn" + mvno_match_data="C Spire" + type="admin,fota,ota" + protocol="IPV4V6" + /> + + <apn carrier="CSpire international" + carrier_id = "1836" + mcc="204" + mnc="04" + apn="tethering.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + mvno_type="spn" + mvno_match_data="C Spire" + type="dun,pam" + protocol="IPV4V6" + /> + + <apn carrier="KPN/Hi 4G LTE Mobiel internet" + carrier_id = "1644" + mcc="204" + mnc="08" + apn="KPN4G.nl" + mmsc="http://mp.mobiel.kpn/mmsc" + mmsproxy="10.10.100.20" + mmsport="5080" + type="default,supl,mms" + /> + + <apn carrier="KPN/Hi Mobiel Internet" + carrier_id = "1644" + mcc="204" + mnc="08" + apn="portalmmm.nl" + mmsc="http://mp.mobiel.kpn/mmsc" + mmsproxy="10.10.100.20" + mmsport="5080" + type="default,supl,mms" + /> + + <apn carrier="MVNO NL" + carrier_id = "2149" + mcc="204" + mnc="08" + apn="internet.mvno.mobi" + user="mvno" + password="mvno" + authtype="1" + type="default,supl" + mvno_match_data="204080950" + mvno_type="imsi" + /> + + <apn carrier="Rabo Mobiel Int." + carrier_id = "2406" + mcc="204" + mnc="08" + apn="rabo" + type="default,supl" + mvno_match_data="Rabo Mobiel" + mvno_type="spn" + /> + + <apn carrier="Rabo Mobiel MMS" + carrier_id = "2406" + mcc="204" + mnc="08" + apn="rabo" + mmsc="http://mp.mobiel.kpn/mmsc" + mmsproxy="10.10.100.10" + mmsport="5080" + type="mms" + mvno_match_data="Rabo Mobiel" + mvno_type="spn" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="204" + mnc="08" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="547275554B3030656E" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="204" + mnc="08" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="54727555533030656E" + /> + + <apn carrier="HOT mobile Internet" + carrier_id = "1991" + mcc="204" + mnc="04" + apn="net.hotm" + type="default,supl" + mvno_match_data="HOT mobile" + mvno_type="spn" + /> + + <apn carrier="HOT mobile MMS" + carrier_id = "1991" + mcc="204" + mnc="04" + apn="mms.hotm" + mmsc="http://mms.hotmobile.co.il" + mmsproxy="80.246.131.99" + mmsport="80" + type="mms" + mvno_match_data="HOT mobile" + mvno_type="spn" + /> + + <apn carrier="Telfort Internet" + carrier_id = "1644" + mcc="204" + mnc="12" + apn="internet" + mmsc="http://mms" + mmsproxy="193.113.200.195" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2386" + mcc="204" + mnc="16" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2386" + mcc="204" + mnc="16" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2386" + mcc="204" + mnc="16" + apn="mms" + user="tmobilemms" + password="tmobilemms" + authtype="1" + mmsc="http://t-mobilemms" + mmsproxy="10.10.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="Ben Internet Abonnee" + carrier_id = "2095" + mcc="204" + mnc="16" + apn="internet.ben" + type="default,supl" + mvno_match_data="BEN NL" + mvno_type="spn" + /> + + <apn carrier="Ben Internet PrePaid" + carrier_id = "2095" + mcc="204" + mnc="16" + apn="basic.internet.ben.data" + type="default,supl" + mvno_match_data="BEN NL" + mvno_type="spn" + /> + + <apn carrier="Ben MMS" + carrier_id = "2095" + mcc="204" + mnc="16" + apn="mms.ben" + authtype="1" + mmsc="http://benmms/" + mmsproxy="10.10.10.11" + mmsport="8080" + type="mms" + mvno_match_data="BEN NL" + mvno_type="spn" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2386" + mcc="204" + mnc="20" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2386" + mcc="204" + mnc="20" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2386" + mcc="204" + mnc="20" + apn="mms" + user="tmobilemms" + password="tmobilemms" + authtype="1" + mmsc="http://t-mobilemms" + mmsproxy="10.10.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="204" + mnc="33" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="EMnify" + carrier_id = "2326" + mcc="206" + mnc="01" + apn="em" + mvno_match_data="206018" + mvno_type="imsi" + type="default,supl" + /> + + <apn carrier="Px MMS" + carrier_id = "1365" + mcc="206" + mnc="01" + apn="EVENT.PROXIMUS.BE" + user="mms" + password="mms" + authtype="1" + mmsc="http://mmsc.proximus.be/mms" + mmsproxy="10.55.14.75" + mmsport="8080" + type="mms" + /> + + <apn carrier="Px Internet" + carrier_id = "1365" + mcc="206" + mnc="01" + apn="INTERNET.PROXIMUS.BE" + type="default,supl" + /> + + <apn carrier="Telenet Internet" + carrier_id = "2270" + mcc="206" + mnc="01" + apn="telenetwap.be" + type="default,supl" + mvno_match_data="20601889" + mvno_type="imsi" + /> + + <apn carrier="Telenet MMS" + carrier_id = "2270" + mcc="206" + mnc="01" + apn="mms.be" + mmsc="http://mmsc.telenet.be" + mmsproxy="195.130.149.100" + mmsport="80" + type="mms" + mvno_match_data="20601889" + mvno_type="imsi" + /> + + <apn carrier="IIJmio (TypeI/Roaming)" + carrier_id = "2106" + mcc="206" + mnc="01" + apn="iijmio.jp" + user="mio@iij" + password="iij" + authtype="3" + protocol="IP" + type="default" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="IIJ" + /> + + <apn carrier="vmobile.jp (Roaming)" + carrier_id = "2106" + mcc="206" + mnc="01" + apn="vmobile.jp" + user="vmobile@jp" + password="vmobile" + authtype="3" + protocol="IP" + type="default" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="IIJ" + /> + + <apn carrier="Telenet Internet" + carrier_id = "2150" + mcc="206" + mnc="05" + apn="telenetwap.be" + type="default,supl" + /> + + <apn carrier="Telenet MMS" + carrier_id = "2150" + mcc="206" + mnc="05" + apn="mms.be" + mmsc="http://mmsc.telenet.be" + mmsproxy="195.130.149.100" + mmsport="80" + type="mms" + /> + + <apn carrier="Mobistar MMS" + carrier_id = "1366" + mcc="206" + mnc="10" + apn="mms.be" + mmsc="http://mmsc.mobistar.be" + mmsproxy="212.65.63.143" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobistar Internet" + carrier_id = "1366" + mcc="206" + mnc="10" + apn="mworld.be" + type="default,supl" + /> + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="206" + mnc="10" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="BE-Transatel" + mvno_type="spn" + /> + + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="206" + mnc="10" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="BB00" + mvno_type="gid" + /> + + <apn carrier="BASE WAP" + carrier_id = "1367" + mcc="206" + mnc="20" + apn="" + type="ia" + /> + + <apn carrier="BASE WAP" + carrier_id = "1367" + mcc="206" + mnc="20" + apn="gprs.base.be" + user="base" + password="base" + authtype="1" + type="default,supl" + /> + + <apn carrier="BASE MMS" + carrier_id = "1367" + mcc="206" + mnc="20" + apn="mms.base.be" + user="base" + password="base" + authtype="1" + mmsc="http://mmsc.base.be" + mmsproxy="217.72.235.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="BICS Internet" + carrier_id = "2132" + mcc="206" + mnc="28" + apn="bicsapn" + type="default,supl" + /> + + <apn carrier="Orange World" + carrier_id = "32" + mcc="208" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="Orange World" + carrier_id = "32" + mcc="208" + mnc="01" + apn="orange" + user="orange" + password="orange" + authtype="1" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "32" + mcc="208" + mnc="01" + apn="orange.acte" + user="orange" + password="orange" + mmsc="http://mms.orange.fr" + mmsproxy="192.168.10.200" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Orange Entreprise" + carrier_id = "32" + mcc="208" + mnc="01" + apn="orange-mib" + proxy="172.16.2.8" + port="8000" + user="orange" + password="orange" + authtype="2" + type="default" + /> + + <apn carrier="Orange Internet" + carrier_id = "32" + mcc="208" + mnc="01" + apn="orange.fr" + authtype="0" + user="orange" + password="orange" + type="dun" + /> + + <apn carrier="Carrefour WAP" + carrier_id = "2133" + mcc="208" + mnc="01" + apn="ofnew.fr" + proxy="192.168.10.100" + port="8080" + user="orange" + password="orange" + authtype="1" + type="default,supl" + mvno_match_data="33" + mvno_type="gid" + /> + + <apn carrier="Carrefour MMS" + carrier_id = "2133" + mcc="208" + mnc="01" + apn="orange.acte" + user="orange" + password="orange" + mmsc="http://mms.orange.fr" + mmsproxy="192.168.10.200" + mmsport="8080" + authtype="1" + type="mms" + mvno_match_data="33" + mvno_type="gid" + /> + + <apn carrier="NRJWEB" + carrier_id = "2005" + mcc="208" + mnc="01" + apn="ofnew.fr" + user="orange" + password="orange" + authtype="1" + type="default,supl" + mvno_match_data="4E" + mvno_type="gid" + /> + + <apn carrier="NRJMMS" + carrier_id = "2005" + mcc="208" + mnc="01" + apn="orange.acte" + user="orange" + password="orange" + mmsc="http://mms.orange.fr" + mmsproxy="192.168.10.200" + mmsport="8080" + authtype="1" + type="mms" + mvno_match_data="4E" + mvno_type="gid" + /> + + <apn carrier="Coriolis" + carrier_id = "2135" + mcc="208" + mnc="01" + apn="coriolis" + type="default,supl" + mvno_match_data="208011511" + mvno_type="imsi" + /> + + <apn carrier="Coriolis MMS" + carrier_id = "2135" + mcc="208" + mnc="01" + apn="mmscoriolis" + mmsc="http://mms.coriolis.fr" + mmsproxy="10.12.0.1" + mmsport="9028" + type="mms" + mvno_match_data="208011511" + mvno_type="imsi" + /> + + + <apn carrier="SFR webphone" + carrier_id = "27" + mcc="208" + mnc="09" + apn="sl2sfr" + mmsc="http://mms1" + mmsproxy="10.151.0.1" + mmsport="8080" + protocol="IP" + type="default,mms,supl,agps,fota" + /> + + <apn carrier="SFR option modem" + carrier_id = "27" + mcc="208" + mnc="09" + apn="websfr" + protocol="IP" + type="dun" + /> + + <apn carrier="Be Aliv" + carrier_id = "2130" + mcc="208" + mnc="09" + apn="pda.newcomobile.com" + type="default,supl" + mvno_match_data="208090021" + mvno_type="imsi" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="208" + mnc="09" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="547275554B3030656E" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="208" + mnc="09" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="54727555533030656E" + /> + + <apn carrier="Coriolis" + carrier_id = "2135" + mcc="208" + mnc="09" + apn="coriolis" + type="default,supl" + mvno_match_data="208090036" + mvno_type="imsi" + /> + + <apn carrier="Coriolis MMS" + carrier_id = "2135" + mcc="208" + mnc="09" + apn="mmscoriolis" + mmsc="http://mms.coriolis.fr" + mmsproxy="10.12.0.1" + mmsport="9028" + type="mms" + mvno_match_data="208090036" + mvno_type="imsi" + /> + + <apn carrier="SFR webphone" + carrier_id = "27" + mcc="208" + mnc="10" + apn="" + type="ia" + /> + + <apn carrier="SFR webphone" + carrier_id = "27" + mcc="208" + mnc="10" + apn="sl2sfr" + mmsc="http://mms1" + mmsproxy="10.151.0.1" + mmsport="8080" + type="default,mms,supl" + /> + + <apn carrier="SFR option Modem" + carrier_id = "27" + mcc="208" + mnc="10" + apn="websfr" + authtype="0" + type="dun" + /> + + <apn carrier="NRJWEB" + carrier_id = "2005" + mcc="208" + mnc="10" + apn="fnetnrj" + type="default,supl" + mvno_match_data="4E" + mvno_type="gid" + /> + + <apn carrier="NRJMMS" + carrier_id = "2005" + mcc="208" + mnc="10" + mmsc="http://mmsnrj" + mmsproxy="10.143.156.5" + mmsport="8080" + apn="mmsnrj" + type="mms" + mvno_match_data="4E" + mvno_type="gid" + /> + + <apn carrier="INTERNET NRJ" + carrier_id = "2005" + mcc="208" + mnc="10" + apn="internetnrj" + authtype="0" + type="dun" + mvno_type="gid" + mvno_match_data="4E" + /> + + <apn carrier="Auchan WAP" + carrier_id = "2272" + mcc="208" + mnc="10" + apn="wap65" + type="default,supl" + mvno_match_data="A MOBILE" + mvno_type="spn" + /> + + <apn carrier="Auchan MMS" + carrier_id = "2272" + mcc="208" + mnc="10" + mmsc="http://mms65" + mmsproxy="10.143.156.8" + mmsport="8080" + apn="mms65" + type="mms" + mvno_match_data="A MOBILE" + mvno_type="spn" + /> + + <apn carrier="WAP LeclercMobile" + carrier_id = "2273" + mcc="208" + mnc="10" + proxy="192.168.21.9" + port="8080" + apn="wap66" + type="default,supl" + mvno_match_data="LeclercMobile" + mvno_type="spn" + /> + + <apn carrier="MMS LeclercMobile" + carrier_id = "2273" + mcc="208" + mnc="10" + mmsc="http://mms66" + mmsproxy="10.143.156.9" + mmsport="8080" + apn="mms66" + type="mms" + mvno_match_data="LeclercMobile" + mvno_type="spn" + /> + + <apn carrier="Coriolis WAP" + carrier_id = "2135" + mcc="208" + mnc="10" + apn="fnetcoriolis" + type="default,supl" + mvno_match_data="12" + mvno_type="gid" + /> + + <apn carrier="Coriolis MMS" + carrier_id = "2135" + mcc="208" + mnc="10" + mmsc="http://mmscoriolis" + mmsproxy="10.143.156.6" + mmsport="8080" + apn="mmscoriolis" + type="mms" + mvno_match_data="12" + mvno_type="gid" + /> + + <apn carrier="Coriolis WEB" + carrier_id = "2135" + mcc="208" + mnc="10" + apn="internetcoriolis" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="gid" + mvno_match_data="12" + /> + + <apn carrier="4G La Poste Mobile" + carrier_id = "2274" + mcc="208" + mnc="10" + apn="" + type="ia" + mvno_match_data="4C" + mvno_type="gid" + /> + + <apn carrier="4G La Poste Mobile" + carrier_id = "2274" + mcc="208" + mnc="10" + apn="sl2sfr" + mmsc="http://mms1" + mmsproxy="010.143.156.003" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="4C" + mvno_type="gid" + /> + + <apn carrier="WEB La Poste Mobile" + carrier_id = "2274" + mcc="208" + mnc="10" + proxy="192.168.21.3" + port="8080" + apn="wapdebitel" + type="default,supl" + mvno_match_data="4C" + mvno_type="gid" + /> + + <apn carrier="MMS La Poste Mobile" + carrier_id = "2274" + mcc="208" + mnc="10" + apn="mmsdebitel" + mmsc="http://mmsdebitel" + mmsproxy="10.143.156.3" + mmsport="8080" + type="mms" + mvno_match_data="4C" + mvno_type="gid" + /> + + <apn carrier="Darty Surf&Mails" + carrier_id = "2275" + mcc="208" + mnc="10" + apn="wap68" + proxy="192.168.21.11" + port="8080" + type="default,supl" + mvno_match_data="44" + mvno_type="gid" + /> + + <apn carrier="Darty MMS" + carrier_id = "2275" + mcc="208" + mnc="10" + apn="mms68" + mmsc="http://mms68/" + mmsproxy="10.143.156.11" + mmsport="8080" + type="mms" + mvno_match_data="44" + mvno_type="gid" + /> + + <apn carrier="Keyyo Mobile Internet" + carrier_id = "2276" + mcc="208" + mnc="10" + apn="internet68" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="Keyyo Mobile" + /> + + <apn carrier="Keyyo Mobile MMS" + carrier_id = "2276" + mcc="208" + mnc="10" + apn="mms68" + authtype="0" + mmsc="http://mms68" + mmsproxy="10.143.156.11" + mmsport="8080" + type="mms" + mvno_type="spn" + mvno_match_data="Keyyo Mobile" + /> + + <apn carrier="Keyyo Mobile Wap" + carrier_id = "2276" + mcc="208" + mnc="10" + apn="wap68" + proxy="192.168.21.11" + port="8080" + authtype="0" + type="default,supl,agps,fota" + mvno_type="spn" + mvno_match_data="Keyyo Mobile" + /> + + <apn carrier="Zero forfait" + carrier_id = "2277" + mcc="208" + mnc="10" + apn="internet68" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="ZERO FORFAIT" + /> + + <apn carrier="Zero forfait MMS" + carrier_id = "2277" + mcc="208" + mnc="10" + apn="mms68" + authtype="0" + mmsc="http://mms68" + mmsproxy="10.143.156.11" + mmsport="8080" + type="mms" + mvno_type="spn" + mvno_match_data="ZERO FORFAIT" + /> + + <apn carrier="WAP RegloMobile" + carrier_id = "2273" + mcc="208" + mnc="10" + apn="wap66" + proxy="192.168.21.9" + port="8080" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="RegloMobile" + /> + + <apn carrier="MMS RegloMobile" + carrier_id = "2273" + mcc="208" + mnc="10" + apn="mms66" + authtype="0" + mmsc="http://mms66" + mmsproxy="10.143.156.9" + mmsport="8080" + type="mms" + mvno_type="spn" + mvno_match_data="RegloMobile" + /> + <apn carrier="Truphone" + carrier_id = "2143" + mcc="208" + mnc="12" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Free" + carrier_id = "1958" + mcc="208" + mnc="15" + apn="free" + mmsc="http://mms.free.fr" + type="default,supl,mms" + /> + + <apn carrier="Free MMS" + carrier_id = "1958" + mcc="208" + mnc="15" + mmsc="http://mms.free.fr" + apn="mmsfree" + type="mms" + /> + + <apn carrier="Free Re Int" + carrier_id = "2127" + mcc="208" + mnc="15" + apn="free.re" + mmsc="http://mms.free.re" + type="default,supl,mms" + mvno_match_data="F2330002" + mvno_type="gid" + /> + + <apn carrier="Iliad Int" + carrier_id = "2124" + mcc="208" + mnc="15" + apn="iliad" + mmsc="http://mms.iliad.it" + type="default,supl,mms" + mvno_match_data="F003" + mvno_type="gid" + /> + + <apn carrier="Legos" + carrier_id = "2151" + mcc="208" + mnc="17" + apn="bornsip" + type="default,supl" + /> + + <apn carrier="Legos MMS" + carrier_id = "2151" + mcc="208" + mnc="17" + mmsc="http://mms.bornsip.fr:8191" + apn="bornsipmms" + type="mms" + /> + + <apn carrier="Bouygues Telecom" + carrier_id = "1487" + mcc="208" + mnc="20" + apn="mmsbouygtel.com" + mmsc="http://mms.bouyguestelecom.fr/mms/wapenc" + mmsproxy="62.201.129.226" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="mobiledata" + mcc="208" + mnc="22" + apn="mobiledata" + mmsc="http://mms" + type="default,supl,mms" + /> + + <apn carrier="netgprs.com" + mcc="208" + mnc="22" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="FR-Transatel" + mvno_type="spn" + /> + + <apn carrier="Virgin mobile" + carrier_id = "1984" + mcc="208" + mnc="23" + apn="virgin-mobile.fr" + proxy="10.6.10.1" + port="8080" + type="default,supl" + /> + + <apn carrier="VM MMS" + carrier_id = "1984" + mcc="208" + mnc="23" + apn="virgin-mobile.fr" + mmsc="http://virginmms.fr" + mmsproxy="10.6.10.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="NRJ WEB" + carrier_id = "2005" + mcc="208" + mnc="26" + apn="fnetnrj" + type="default,supl" + /> + + <apn carrier="NRJ MMS" + carrier_id = "2005" + mcc="208" + mnc="26" + apn="mmsnrj" + mmsc="http://mmsnrj" + mmsproxy="10.143.156.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Coriolis" + carrier_id = "2135" + mcc="208" + mnc="27" + apn="coriolis" + type="default,supl" + /> + + <apn carrier="Coriolis MMS" + carrier_id = "2135" + mcc="208" + mnc="27" + apn="mmscoriolis" + mmsc="http://mms.coriolis.fr" + mmsproxy="10.12.0.1" + mmsport="9028" + type="mms" + /> + + + <apn carrier="Internet móvil" + mcc="214" + mnc="01" + apn="airtelwap.es" + user="wap@wap" + password="wap125" + authtype="1" + type="default,supl" + /> + + <apn carrier="INTERNET" + mcc="214" + mnc="01" + apn="airtelnet.es" + authtype="1" + user="vodafone" + password="vodafone" + type="dun" + /> + + <apn carrier="MMS VODAFONE" + mcc="214" + mnc="01" + apn="mms.vodafone.net" + user="wap@wap" + password="wap125" + mmsc="http://mmsc.vodafone.es/servlets/mms" + mmsproxy="212.73.32.10" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="IMS Vodafone" + mcc="214" + mnc="01" + apn="ims" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="ALTECOM" + carrier_id = "2131" + mcc="214" + mnc="02" + apn="altecom.net" + type="default" + /> + + <apn carrier="FIBRACAT" + carrier_id = "2136" + mcc="214" + mnc="02" + apn="fibracat.cat" + type="default" + mvno_type="spn" + mvno_match_data="FIBRACAT" + /> + + <apn carrier="Orange Internet Móvil" + carrier_id = "2369" + mcc="214" + mnc="03" + apn="" + type="ia" + /> + + <apn carrier="Orange Internet Móvil" + carrier_id = "678" + mcc="214" + mnc="03" + apn="orangeworld" + user="orange" + password="orange" + authtype="1" + mvno_type="spn" + mvno_match_data="Orange" + type="default" + /> + + <apn carrier="Orange MMS" + carrier_id = "678" + mcc="214" + mnc="03" + apn="orangemms" + user="orange" + password="orange" + mmsc="http://mms.orange.es" + mmsproxy="172.22.188.25" + mmsport="8080" + authtype="1" + mvno_type="spn" + mvno_match_data="Orange" + type="mms" + /> + + <apn carrier="Orange Internet PC" + carrier_id = "2369" + mcc="214" + mnc="03" + apn="internet" + authtype="0" + user="orange" + password="orange" + type="dun" + /> + + <apn carrier="Euskaltel Internet" + mcc="214" + mnc="03" + apn="internet.euskaltel.mobi" + user="CLIENTE" + password="EUSKALTEL" + authtype="1" + type="default,supl" + mvno_type="imsi" + mvno_match_data="2140359" + /> + + <apn carrier="Euskaltel MMS" + mcc="214" + mnc="03" + apn="euskaltelmms.euskaltel.mobi" + user="MMS" + password="EUSKALTEL" + authtype="1" + mmsc="http://mms.euskaltel.mobi" + mmsproxy="172.16.18.74" + mmsport="8080" + type="mms" + mvno_type="imsi" + mvno_match_data="2140359" + /> + + <apn carrier="Carrefour" + carrier_id = "2133" + mcc="214" + mnc="03" + apn="CARREFOURINTERNET" + authtype="1" + type="default,supl" + mvno_type="imsi" + mvno_match_data="2140352xxxxxxxx" + /> + + <apn carrier="Carrefour MMS" + carrier_id = "2133" + mcc="214" + mnc="03" + apn="CARREFOURMMS" + user="CARREFOUR" + password="CARREFOUR" + authtype="1" + mmsc="http://mms.orange.es" + mmsproxy="172.022.188.025" + mmsport="8080" + mvno_type="imsi" + mvno_match_data="2140352xxxxxxxx" + type="mms" + /> + + <apn carrier="Happy Internet" + carrier_id = "2297" + mcc="214" + mnc="03" + apn="internettph" + type="default,supl" + mvno_type="spn" + mvno_match_data="Happy" + /> + + <apn carrier="RACC INTERNET" + carrier_id = "2298" + mcc="214" + mnc="03" + apn="internet.racc.net" + user="CLIENTERACC" + password="RACC" + type="default,supl" + mvno_type="spn" + mvno_match_data="RACC" + /> + + <apn carrier="RACC MMS" + carrier_id = "2298" + mcc="214" + mnc="03" + apn="mms.racc.net" + user="MMS" + password="RACC" + mmsc="http://mms.racc.net" + mmsproxy="172.16.18.74" + mmsport="8080" + mvno_type="spn" + mvno_match_data="RACC" + type="mms" + /> + + <apn carrier="CABLE movil Internet" + carrier_id = "2299" + mcc="214" + mnc="03" + apn="internettph" + type="default,supl" + mvno_type="spn" + mvno_match_data="CABLE movil" + /> + + <apn carrier="MASMovil Internet" + carrier_id = "2300" + mcc="214" + mnc="03" + apn="internetmas" + type="default,supl" + mvno_type="spn" + mvno_match_data="MASMovil" + /> + + <apn carrier="Ibercom Internet" + carrier_id = "2301" + mcc="214" + mnc="03" + apn="ibercominternet" + type="default,supl" + mvno_type="spn" + mvno_match_data="Ibercom" + /> + + <apn carrier="jazzinternet" + carrier_id = "1974" + mcc="214" + mnc="03" + apn="jazzinternet" + mvno_type="spn" + mvno_match_data="JAZZTEL" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1974" + mcc="214" + mnc="03" + apn="jazzmms" + user="" + password="" + authtype="1" + mmsc="http://jazztelmms.com/servlets/mms" + mmsproxy="37.132.0.10" + mmsport="8080" + mvno_type="spn" + mvno_match_data="JAZZTEL" + type="mms" + /> + + <apn carrier="internet simyo" + carrier_id = "2125" + mcc="214" + mnc="03" + apn="orangeworld" + authtype="1" + user="orange" + password = "orange" + mvno_type="spn" + mvno_match_data="simyo" + type="default,supl" + /> + + <apn carrier="simyo MMS" + carrier_id = "2125" + mcc="214" + mnc="03" + apn="orangemms" + user="orange" + password="orange" + authtype="1" + mmsc="http://mms.orange.es" + mmsproxy="172.22.188.25" + mmsport="8080" + mvno_type="spn" + mvno_match_data="simyo" + type="mms" + /> + + <apn carrier="Yoigo Internet" + carrier_id = "679" + mcc="214" + mnc="04" + apn="" + type="ia" + /> + + <apn carrier="Yoigo Internet" + carrier_id = "679" + mcc="214" + mnc="04" + apn="internet" + type="default,supl" + /> + + <apn carrier="Yoigo MMS" + carrier_id = "679" + mcc="214" + mnc="04" + apn="mms" + mmsc="http://mmss/" + mmsproxy="193.209.134.141" + mmsport="80" + type="mms" + /> + + <apn carrier="Tuenti" + carrier_id = "34" + mcc="214" + mnc="05" + apn="tuenti.com" + authtype="1" + user="tuenti" + password="tuenti" + mmsc="http://tuenti.com" + mmsproxy="10.138.255.43" + mmsport="8080" + /> + + <apn carrier="INET Roaming" + mcc="214" + mnc="05" + apn="inet.es" + user="" + password="" + port="" + proxy="" + type="default,supl,fota,hipri" + roaming_protocol="IPV4V6" + mvno_type="imsi" + mvno_match_data="214050104xxxxxx" + /> + + <apn carrier="DIGI Spain" + carrier_id="2442" + mcc="214" + mnc="05" + apn="internet.digimobil.es" + type="default,supl" + mvno_type="gid" + mvno_match_data="44474553" + /> + + <apn carrier="DIGI Italy" + carrier_id="2443" + mcc="214" + mnc="05" + apn="digi.mobile" + type="default,supl" + mvno_type="gid" + mvno_match_data="44474954" + /> + + <apn carrier="INTERNET GPRS" + carrier_id = "1909" + mcc="214" + mnc="06" + apn="airtelnet.es" + user="vodafone" + password="vodafone" + type="default,supl" + /> + + <apn carrier="MMS Vodafone" + carrier_id = "1909" + mcc="214" + mnc="06" + apn="mms.vodafone.net" + user="wap@wap" + password="wap125" + mmsc="http://mmsc.vodafone.es/servlets/mms" + mmsproxy="212.73.32.10" + mmsport="80" + type="mms" + /> + + <apn carrier="Euskaltel MMS" + mcc="214" + mnc="06" + apn="euskaltelmms.euskaltel.mobi" + user="MMS" + password="EUSKALTEL" + mmsc="http://mms.euskaltel.mobi" + mmsproxy="172.16.18.74" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Euskaltel Internet" + mcc="214" + mnc="06" + apn="internet.euskaltel.mobi" + user="CLIENTE" + password="EUSKALTEL" + authtype="1" + type="default,supl" + mvno_match_data="0008" + mvno_type="gid" + /> + + <apn carrier="Internet R" + carrier_id = "2278" + mcc="214" + mnc="06" + apn="internet.mundo-r.com" + authtype="1" + type="default,supl" + mvno_match_data="2140612" + mvno_type="imsi" + /> + + <apn carrier="MMS R" + carrier_id = "2278" + mcc="214" + mnc="06" + apn="mms.mundo-r.com" + mmsc="http://mms.mundo-r.com" + mmsproxy="10.0.157.169" + mmsport="8080" + authtype="1" + type="mms" + mvno_match_data="2140612" + mvno_type="imsi" + /> + + <apn carrier="TeleCable Internet" + carrier_id = "2112" + mcc="214" + mnc="06" + apn="internet.telecable.es" + user="telecable" + password="telecable" + authtype="1" + type="default,supl" + mvno_match_data="2140613" + mvno_type="imsi" + /> + + <apn carrier="TeleCable MMS" + carrier_id = "2112" + mcc="214" + mnc="06" + apn="mms.telecable.es" + user="telecable" + password="telecable" + mmsc="http://mms.telecable.es/mms/" + mmsproxy="212.89.0.84" + mmsport="8080" + authtype="1" + type="mms" + mvno_match_data="2140613" + mvno_type="imsi" + /> + + <apn carrier="Eroski Movil GPRS" + carrier_id = "2279" + mcc="214" + mnc="06" + apn="gprs.eroskimovil.es" + user="wap@wap" + password="wap125" + authtype="1" + type="default,supl" + mvno_match_data="2140606" + mvno_type="imsi" + /> + + <apn carrier="Eroski Movil MMS" + carrier_id = "2279" + mcc="214" + mnc="06" + apn="mms.eroskimovil.es" + user="wap@wap" + password="wap125" + mmsc="http://mms.eroskimovil.es/servlets/mms" + mmsproxy="212.73.32.10" + mmsport="80" + authtype="1" + type="mms" + mvno_match_data="2140606" + mvno_type="imsi" + /> + + <apn carrier="DUN" + carrier_id = "2280" + mcc="214" + mnc="06" + apn="gprs.pepephone.com" + authtype="0" + type="dun" + mvno_type="spn" + mvno_match_data="pepephone" + /> + + <apn carrier="Internet" + carrier_id = "2280" + mcc="214" + mnc="06" + apn="gprsmov.pepephone.com" + authtype="0" + type="default,supl,agps,fota" + mvno_type="spn" + mvno_match_data="pepephone" + /> + + <apn carrier="MMS" + carrier_id = "2280" + mcc="214" + mnc="06" + apn="mms.pepephone.com" + authtype="0" + user="wap@wap" + password="wap125" + mmsc="http://mms.pepephone.com/servlets/mms" + mmsproxy="212.73.32.10" + mmsport="80" + type="mms" + mvno_type="spn" + mvno_match_data="pepephone" + /> + + <apn carrier="Mobiland" + carrier_id = "450" + mcc="213" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="Movistar" + carrier_id = "34" + mcc="214" + mnc="07" + apn="telefonica.es" + user="telefonica" + password="telefonica" + mmsc="http://mms.movistar.com" + mmsproxy="10.138.255.5" + mmsport="8080" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="Jazztel Internet" + carrier_id = "1974" + mcc="214" + mnc="07" + apn="jazzinternet" + type="default,supl" + mvno_match_data="JAZZTEL" + mvno_type="spn" + /> + + <apn carrier="Jazztel MMS" + carrier_id = "1974" + mcc="214" + mnc="07" + apn="jazzmms" + user="" + password="" + mmsc="http://jazztelmms.com/servlets/mms" + mmsproxy="37.132.0.10" + mmsport="8080" + authtype="1" + type="mms" + mvno_match_data="JAZZTEL" + mvno_type="spn" + /> + + <apn carrier="Conexióompartida" + carrier_id = "34" + mcc="214" + mnc="07" + apn="movistar.es" + authtype="1" + user="MOVISTAR" + password="MOVISTAR" + type="dun" + /> + + <apn carrier="T-2" + carrier_id = "2281" + mcc="214" + mnc="07" + apn="internet.t-2.net" + mmsc="http://www.mms.t-2.net:8002" + mmsproxy="172.20.18.137" + mmsport="8080" + mvno_type="imsi" + mvno_match_data="2140759577xxxxx" + type="default,ims,mms,supl" + /> + + <apn carrier="T-2" + carrier_id = "2281" + mcc="214" + mnc="07" + apn="internet.t-2.net" + mmsc="http://www.mms.t-2.net:8002" + mmsproxy="172.20.18.137" + mmsport="8080" + type="default,ims,mms,supl" + mvno_type="imsi" + mvno_match_data="2140796692xxxxx" + /> + + <apn carrier="Euskaltel MMS" + carrier_id = "1909" + mcc="214" + mnc="08" + apn="euskaltelmms.euskaltel.mobi" + user="MMS" + password="EUSKALTEL" + mmsc="http://mms.euskaltel.mobi" + mmsproxy="172.16.18.74" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Euskaltel Internet" + carrier_id = "1909" + mcc="214" + mnc="08" + apn="internet.euskaltel.mobi" + user="CLIENTE" + password="EUSKALTEL" + authtype="1" + type="default,supl" + /> + + <apn carrier="TeleCable Internet" + mcc="214" + mnc="16" + apn="internet.telecable.es" + user="telecable" + password="telecable" + type="default,supl" + /> + + <apn carrier="TeleCable MMS" + mcc="214" + mnc="16" + apn="mms.telecable.es" + user="telecable" + password="telecable" + mmsc="http://mms.telecable.es/mms/" + mmsproxy="212.89.0.84" + mmsport="8080" + type="mms" + /> + + <apn carrier="ONO Internet" + carrier_id = "1976" + mcc="214" + mnc="18" + apn="internet.ono.com" + type="default,supl" + /> + + <apn carrier="ONO MMS" + carrier_id = "1976" + mcc="214" + mnc="18" + apn="mms.ono.com" + mmsc="http://mms.ono.com/" + mmsproxy="10.126.0.50" + mmsport="8080" + type="mms" + /> + + <apn carrier="internet simyo" + carrier_id = "2125" + mcc="214" + mnc="19" + apn="orangeworld" + authtype="1" + user="orange" + password = "orange" + type="default,supl" + /> + + <apn carrier="simyo MMS" + carrier_id = "2125" + mcc="214" + mnc="19" + apn="orangemms" + user="orange" + password="orange" + authtype="1" + mmsc="http://mms.orange.es" + mmsproxy="172.22.188.25" + mmsport="8080" + type="mms" + /> + + <apn carrier="jazzinternet" + carrier_id = "1974" + mcc="214" + mnc="21" + apn="" + type="ia" + /> + + <apn carrier="jazzinternet" + carrier_id = "1974" + mcc="214" + mnc="21" + apn="jazzinternet" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1974" + mcc="214" + mnc="21" + apn="jazzmms" + user="" + password="" + authtype="1" + mmsc="http://jazztelmms.com/servlets/mms" + mmsproxy="37.132.0.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="DIGI Spain" + carrier_id="2442" + mcc="214" + mnc="22" + apn="internet.digimobil.es" + type="default,supl" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="214" + mnc="27" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Tuenti" + carrier_id = "2357" + mcc="214" + mnc="32" + apn="tuenti.com" + user="tuenti" + password="tuenti" + authtype="3" + mmsc="http://tuenti.com" + mmsproxy="10.138.255.43" + mmsport="8080" + type="default,mms,supl" + mvno_type="spn" + mvno_match_data="Tuenti" + /> + + <apn carrier="INET Internet" + mcc="214" + mnc="34" + apn="inet.es" + user="" + password="" + port="" + proxy="" + type="default,supl,fota,hipri" + protocol="IPV4V6" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1534" + mcc="216" + mnc="01" + apn="mms" + mmsc="http://mmsc.telenor.hu/" + mmsproxy="84.225.255.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telenor Online" + carrier_id = "1534" + mcc="216" + mnc="01" + apn="online" + type="default,supl" + /> + + <apn carrier="Djuice MMS" + mcc="216" + mnc="01" + apn="mms" + mmsproxy="84.225.255.1" + mmsport="8080" + mmsc="http://mmsc.pgsm.hu/" + type="mms" + authtype="0" + mvno_match_data="Djuice" + mvno_type="spn" + /> + + <apn carrier="Djuice NET" + mcc="216" + mnc="01" + apn="net" + type="default" + authtype="0" + mvno_match_data="Djuice" + mvno_type="spn" + /> + + <apn carrier="Djuice WAP" + mcc="216" + mnc="01" + apn="wap" + proxy="84.225.255.1" + port="8080" + type="default" + authtype="0" + mvno_match_data="Djuice" + mvno_type="spn" + /> + + <apn carrier="T-Mobile H" + carrier_id = "2401" + mcc="216" + mnc="30" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile H MMS" + carrier_id = "2401" + mcc="216" + mnc="30" + apn="internet.telekom" + mmsc="http://mms.t-mobile.hu/servlets/mms" + mmsproxy="212.51.126.10" + mmsport="8080" + type="mms" + authtype="1" + /> + + <apn carrier="T-Mobile H" + carrier_id = "2401" + mcc="216" + mnc="30" + apn="internet.telekom" + type="default,supl" + authtype="1" + /> + + <apn carrier="Vodafone Internet" + carrier_id = "1535" + mcc="216" + mnc="70" + apn="internet.vodafone.net" + type="default,supl" + authtype="0" + mvno_match_data="21670xx2xxx" + mvno_type="imsi" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "1535" + mcc="216" + mnc="70" + apn="mms.vodafone.net" + mmsproxy="80.244.97.2" + mmsport="8080" + mmsc="http://mms.vodafone.hu/servlets/mms" + type="mms" + authtype="0" + mvno_match_data="21670xx2xxx" + mvno_type="imsi" + /> + + <apn carrier="Vodafone Live!" + carrier_id = "1535" + mcc="216" + mnc="70" + apn="wap.vodafone.net" + user="vodawap" + password="vodawap" + proxy="10.9.8.7" + port="8080" + type="default,supl" + authtype="1" + mvno_match_data="21670xx2xxx" + mvno_type="imsi" + /> + + <apn carrier="Vodafone Internet VitaMAX" + mcc="216" + mnc="70" + apn="vitamax.internet.vodafone.net" + type="default,supl" + mvno_match_data="21670xx1xxx" + mvno_type="imsi" + /> + + <apn carrier="Vodafone MMS" + mcc="216" + mnc="70" + apn="mms.vodafone.net" + mmsproxy="80.244.97.2" + mmsport="8080" + mmsc="http://mms.vodafone.hu/servlets/mms" + type="mms" + mvno_match_data="21670xx1xxx" + mvno_type="imsi" + /> + + <apn carrier="Vodafone Live! VitaMAX" + mcc="216" + mnc="70" + apn="vitamax.wap.vodafone.net" + user="vodawap" + password="vodawap" + proxy="10.9.8.7" + port="8080" + type="default,supl" + authtype="1" + mvno_match_data="21670xx1xxx" + mvno_type="imsi" + /> + + <apn carrier="HT Eronet WAP" + carrier_id = "1357" + mcc="218" + mnc="03" + apn="wap.eronet.ba" + proxy="10.12.3.10" + port="8080" + type="default,supl" + /> + + <apn carrier="HT Eronet GPRS" + carrier_id = "1357" + mcc="218" + mnc="03" + apn="gprs.eronet.ba" + type="default,supl" + /> + + <apn carrier="Ht Eronet MMS" + carrier_id = "1357" + mcc="218" + mnc="03" + apn="mms.eronet.ba" + mmsc="http://mms.gprs.eronet.ba/mms/wapenc" + mmsproxy="10.12.3.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="m:tel" + carrier_id = "1358" + mcc="218" + mnc="05" + apn="3g1" + proxy="192.168.61.10" + port="80" + type="default,supl" + /> + + <apn carrier="mtelgprs" + carrier_id = "1358" + mcc="218" + mnc="05" + apn="3g1" + type="default,supl" + /> + + <apn carrier="mtelmms" + carrier_id = "1358" + mcc="218" + mnc="05" + apn="mtelmms" + mmsc="http://mmsc.mtel.ba/mms/wapenc" + mmsproxy="192.168.61.11" + mmsport="80" + type="mms" + /> + + <apn carrier="BHMobileInternet" + carrier_id = "1359" + mcc="218" + mnc="90" + apn="active.bhmobile.ba" + type="default,supl" + protocol="IPV4V6" + /> + + <apn carrier="BHMobileMMS" + carrier_id = "1359" + mcc="218" + mnc="90" + apn="mms.bhmobile.ba" + mmsc="http://mms.bhmobile.ba/servlets/mms" + mmsproxy="195.222.56.41" + mmsport="8080" + type="mms" + protocol="IPV4V6" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2365" + mcc="219" + mnc="01" + apn="mms.htgprs" + mmsc="http://mms.t-mobile.hr/servlets/mms" + mmsproxy="10.12.0.4" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="T-Mobile" + carrier_id = "2365" + mcc="219" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2365" + mcc="219" + mnc="01" + apn="internet.ht.hr" + authtype="1" + type="default,supl" + /> + + <apn carrier="bonbon Internet" + carrier_id = "2091" + mcc="219" + mnc="01" + apn="web.htgprs" + authtype="1" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="bonbon" + /> + + <apn carrier="bonbon MMS" + carrier_id = "2091" + mcc="219" + mnc="01" + apn="mms.htgprs" + authtype="1" + mmsc="http://mms.bonbon.com.hr/servlets/mms" + mmsproxy="10.12.0.4" + mmsport="8080" + type="mms" + mvno_type="spn" + mvno_match_data="bonbon" + /> + + <apn carrier="Tele2" + carrier_id = "1529" + mcc="219" + mnc="02" + apn="internet.tele2.hr" + mmsc="http://mmsc.tele2.hr" + mmsproxy="193.12.40.66" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Broadband" + carrier_id = "1530" + mcc="219" + mnc="10" + apn="" + type="ia" + /> + + <apn carrier="Broadband" + carrier_id = "1530" + mcc="219" + mnc="10" + apn="data.vip.hr" + user="38591" + password="38591" + authtype="1" + proxy="212.91.99.91" + port="8080" + type="default,supl" + /> + + <apn carrier="VIP.mms" + carrier_id = "1530" + mcc="219" + mnc="10" + apn="mms.vipnet.hr" + mmsc="http://mms.vipnet.hr/servlets/mms" + mmsproxy="212.91.99.91" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telenor internet" + carrier_id = "1012" + mcc="220" + mnc="01" + apn="internet" + user="telenor" + password="gprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1012" + mcc="220" + mnc="01" + apn="mms" + mmsc="http://mms.telenor.rs/servlets/mms" + mmsproxy="217.65.192.33" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telenor MNE internet" + carrier_id = "1012" + mcc="220" + mnc="02" + apn="internet" + user="gprs" + password="gprs" + proxy="192.168.246.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Telenor MNE mms" + carrier_id = "1012" + mcc="220" + mnc="02" + apn="mms" + user="mms" + password="mms" + mmsc="http://mm.vor.telenor.me" + mmsproxy="192.168.246.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="mt:s wap" + carrier_id = "1013" + mcc="220" + mnc="03" + apn="gprswap" + user="mts" + password="064" + proxy="172.17.88.198" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="mt:s mms" + carrier_id = "1013" + mcc="220" + mnc="03" + apn="mms" + user="mts" + password="064" + mmsc="http://mms.mts064.telekom.rs/mms/wapenc" + mmsproxy="172.17.85.131" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="MTS Internet RS" + carrier_id = "1013" + mcc="220" + mnc="03" + apn="gprsinternet" + authtype="0" + user="mts" + password="064" + type="default,supl,agps,fota,dun" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "10" + mcc="220" + mnc="04" + apn="mms" + user="38267" + password="38267" + mmsc="http://192.168.180.100/servlets/mms" + mmsproxy="10.0.5.19" + mmsport="8080" + type="mms" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "10" + mcc="220" + mnc="04" + apn="tmcg-wnw" + user="38267" + password="38267" + proxy="10.0.5.19" + port="8080" + type="default,supl" + /> + + <apn carrier="SaskTel" + carrier_id = "580" + mcc="204" + mnc="04" + apn="pda.stm.sk.ca" + type="default,mms,supl" + mmsc="http://mms.sasktel.com/" + mmsproxy="mig.sasktel.com" + mmsport="80" + mvno_match_data="5A" + mvno_type="gid" + /> + + <apn carrier="agms" + carrier_id = "2351" + mcc="204" + mnc="65" + apn="agms" + type="default,supl" + /> + + <apn carrier="Vip GPRS" + carrier_id = "1014" + mcc="220" + mnc="05" + apn="vipmobile" + user="vipmobile" + password="vipmobile" + proxy="212.15.182.82" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vip MMS" + carrier_id = "1014" + mcc="220" + mnc="05" + apn="vipmobile.mms" + user="vipmobile" + password="vipmobile" + mmsc="http://mmsc.vipmobile.rs" + mmsproxy="212.15.182.82" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="TIM WAP" + carrier_id = "33" + mcc="222" + mnc="01" + apn="wap.tim.it" + type="default,supl" + /> + + <apn carrier="TIM DUN (IT)" + carrier_id = "33" + mcc="222" + mnc="01" + apn="ibox.tim.it" + authtype="0" + type="dun" + /> + + <apn carrier="TIM MMS" + carrier_id = "33" + mcc="222" + mnc="01" + apn="unico.tim.it" + mmsc="http://mms.tim.it/servlets/mms" + mmsproxy="213.230.130.89" + mmsport="80" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1895" + mcc="222" + mnc="01" + apn="internet.windmobile.ca" + type="default,supl" + protocol="IPV4V6" + mvno_match_data="FFFFFF00" + mvno_type="gid" + /> + + <apn carrier="MMS" + carrier_id = "1895" + mcc="222" + mnc="01" + apn="mms.windmobile.ca" + mmsc="http://mms.windmobile.ca" + mmsproxy="74.115.197.70" + mmsport="8080" + type="mms" + mvno_match_data="FFFFFF00" + mvno_type="gid" + /> + + <apn carrier="MMS" + carrier_id = "1912" + mcc="222" + mnc="01" + authtype="0" + mmsc="http://mms.iusacell3g.com/" + type="mms" + user="mmsiusacellgsm" + password="mmsiusacellgsm" + apn="mms.iusacellgsm.mx" + mvno_type="spn" + mvno_match_data="IUSACELL" + /> + + <apn carrier="Modem" + carrier_id = "1912" + mcc="222" + mnc="01" + authtype="0" + type="dun" + user="iusacellgsm" + password="iusacellgsm" + apn="modem.iusacellgsm.mx" + mvno_type="spn" + mvno_match_data="IUSACELL" + /> + + <apn carrier="Internet" + carrier_id = "1912" + mcc="222" + mnc="01" + authtype="0" + type="default" + user="iusacellgsm" + password="iusacellgsm" + apn="web.iusacellgsm.mx" + mvno_type="spn" + mvno_match_data="IUSACELL" + /> + + <apn carrier="MMS" + carrier_id = "1912" + mcc="222" + mnc="01" + apn="mms.iusacellgsm.mx" + authtype="0" + mmsc="http://mms.iusacell3g.com/" + type="mms" + user="mmsiusacellgsm" + password="mmsiusacellgsm" + mvno_type="spn" + mvno_match_data="UNEFON" + /> + + <apn carrier="Modem" + carrier_id = "1912" + mcc="222" + mnc="01" + apn="modem.iusacellgsm.mx" + authtype="0" + type="dun" + user="iusacellgsm" + password="iusacellgsm" + mvno_type="spn" + mvno_match_data="UNEFON" + /> + + <apn carrier="Internet" + carrier_id = "1912" + mcc="222" + mnc="01" + apn="web.iusacellgsm.mx" + authtype="0" + type="default" + user="iusacellgsm" + password="iusacellgsm" + mvno_type="spn" + mvno_match_data="UNEFON" + /> + + <apn carrier="NOVERCA MMS" + carrier_id = "2282" + mcc="222" + mnc="01" + apn="mms.noverca.it" + authtype="0" + mmsc="http://mms.noverca.it/" + mmsproxy="213.230.130.89" + mmsport="80" + type="mms" + mvno_type="spn" + mvno_match_data="Noverca" + /> + + <apn carrier="NOVERCA WEB" + carrier_id = "2282" + mcc="222" + mnc="01" + apn="web.noverca.it" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="Noverca" + /> + + <apn carrier="GigSky" + carrier_id="2459" + mcc="222" + mnc="01" + apn="gigsky" + type="default" + mvno_type="spn" + mvno_match_data="GigSky" + /> + + <apn carrier="Acc. Internet da cell" + mcc="222" + mnc="10" + apn="" + type="ia" + protocol="IPV4V6" + /> + + <apn carrier="MMS Vodafone" + mcc="222" + mnc="10" + apn="mms.vodafone.it" + mmsc="http://mms.vodafone.it/servlets/mms" + mmsproxy="10.128.224.10" + mmsport="80" + type="mms" + /> + + <apn carrier="ho." + carrier_id = "2455" + mcc="222" + mnc="10" + apn="web.ho-mobile.it" + authtype="0" + type="default,supl,hipri,fota" + mvno_type="spn" + mvno_match_data="ho." + /> + + <apn carrier="ho. (Tethering)" + carrier_id = "2455" + mcc="222" + mnc="10" + apn="internet.ho-mobile.it" + authtype="0" + type="dun" + mvno_type="spn" + mvno_match_data="ho." + /> + + <apn carrier="Acc. Internet da cell" + mcc="222" + mnc="10" + apn="mobile.vodafone.it" + type="default,supl" + /> + + <apn carrier="Tethering Internet" + mcc="222" + mnc="10" + apn="web.omnitel.it" + authtype="0" + mmsport="80" + type="dun" + /> + + <apn carrier="IMS Vodafone" + mcc="222" + mnc="10" + apn="ims" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="PosteMobile" + carrier_id = "2303" + mcc="222" + mnc="10" + apn="wap.postemobile.it" + authtype="0" + type="default,supl,agps,fota" + mvno_type="spn" + mvno_match_data="PosteMobile" + /> + + <apn carrier="PosteMobile (DUN)" + carrier_id = "2303" + mcc="222" + mnc="10" + apn="internet.postemobile.it" + authtype="0" + type="dun" + mvno_type="spn" + mvno_match_data="PosteMobile" + /> + + <apn carrier="PosteMobile MMS" + carrier_id = "2303" + mcc="222" + mnc="10" + apn="mms.postemobile.it" + authtype="0" + mmsc="http://mms.postemobile.it/servlets/mms" + mmsproxy="10.128.224.10" + mmsport="80" + type="mms" + mvno_type="spn" + mvno_match_data="PosteMobile" + /> + + <apn carrier="ErgMobile WAP" + carrier_id = "2304" + mcc="222" + mnc="10" + apn="mobile.erg.it" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="ERG" + /> + + <apn carrier="DailyTelecomWAP" + carrier_id = "2438" + mcc="222" + mnc="10" + apn="wap.dtm.it" + type="default,supl,dun" + mvno_type="spn" + mvno_match_data="Daily Telecom" + /> + + <apn carrier="DIGI Italy" + carrier_id="2443" + mcc="222" + mnc="36" + apn="digi.mobile" + type="default,supl" + /> + + <apn carrier="Iliad" + carrier_id = "2124" + mcc="222" + mnc="50" + apn="iliad" + mmsc="http://mms.iliad.it" + type="default,supl,mms" + /> + + <apn carrier="WEB CoopVoce" + mcc="222" + mnc="53" + apn="internet.coopvoce.it" + type="default" + /> + + <apn carrier="MMS CoopVoce" + mcc="222" + mnc="53" + apn="message.coopvoce.it" + type="mms" + mmsc="http://mms.coop.it/servlets/mms" + mmsproxy="213.230.130.89" + mmsport="80" + /> + + <apn carrier="Plintron" + mcc="222" + mnc="54" + apn="data.plintron.it" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Plintron" + /> + + <apn carrier="INTERNET" + carrier_id = "1573" + mcc="222" + mnc="88" + apn="internet.it" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1573" + mcc="222" + mnc="88" + apn="mms.it" + mmsc="http://mms.windtre.it" + mmsproxy="mmsproxy.windtre.it" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1895" + mcc="222" + mnc="88" + apn="internet.windmobile.ca" + type="default,supl" + protocol="IPV4V6" + mvno_match_data="FFFFFF00" + mvno_type="gid" + /> + + <apn carrier="MMS" + carrier_id = "1895" + mcc="222" + mnc="88" + apn="mms.windmobile.ca" + mmsc="http://mms.windmobile.ca" + mmsproxy="74.115.197.70" + mmsport="8080" + type="mms" + mvno_match_data="FFFFFF00" + mvno_type="gid" + /> + + <apn carrier="INTERNET" + carrier_id = "1575" + mcc="222" + mnc="99" + apn="internet.it" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1575" + mcc="222" + mnc="99" + apn="mms.it" + mmsc="http://mms.windtre.it" + mmsproxy="mmsproxy.windtre.it" + mmsport="8080" + type="mms" + /> + + <apn carrier="Fastweb WEB" + carrier_id = "2039" + mcc="222" + mnc="99" + apn="apn.fastweb.it" + mmsc="http://mms.fastweb.it/mms/wapenc" + mmsproxy="10.0.65.9" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="FASTWEB" + mvno_type="spn" + /> + + <apn carrier="Vodafone live!" + carrier_id = "2391" + mcc="226" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="Vodafone live!" + carrier_id = "2391" + mcc="226" + mnc="01" + apn="live.vodafone.com" + user="live" + password="vodafone" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "2391" + mcc="226" + mnc="01" + apn="mms.vodafone.ro" + user="mms" + password="vodafone" + mmsc="http://multimedia/servlets/mms" + mmsproxy="193.230.161.231" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Vodafone live!PRE" + carrier_id = "2391" + mcc="226" + mnc="01" + apn="live.pre.vodafone.com" + proxy="193.230.161.231" + port="8080" + authtype="0" + user="live" + password="vodafone" + type="default" + /> + + <apn carrier="Cosmote Connect Mobile" + mcc="226" + mnc="03" + apn="" + type="ia" + /> + + <apn carrier="Cosmote Connect Mobile" + mcc="226" + mnc="03" + apn="broadband" + type="default,supl" + /> + + <apn carrier="Cosmote MMS" + mcc="226" + mnc="03" + apn="mms" + user="mms" + password="mms" + mmsc="http://mmsc1.mms.cosmote.ro:8002" + mmsproxy="10.252.1.62" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="web'n'walk" + mcc="226" + mnc="03" + apn="wnw" + user="wnw" + password="wnw" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1959" + mcc="226" + mnc="05" + apn="mms" + mmsc="http://10.10.3.133:8002" + mmsproxy="10.10.3.130" + mmsport="8080" + type="mms" + /> + + <apn carrier="Digi.Mobil" + carrier_id = "1959" + mcc="226" + mnc="05" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="DIGI Spain" + carrier_id="2442" + mcc="226" + mnc="05" + apn="internet.digimobil.es" + type="default,supl" + mvno_type="gid" + mvno_match_data="44474553" + /> + + <apn carrier="DIGI Italy" + carrier_id="2443" + mcc="226" + mnc="05" + apn="digi.mobile" + type="default,supl" + mvno_type="gid" + mvno_match_data="44474954" + /> + + <apn carrier="Cosmote Connect Mobile" + mcc="226" + mnc="06" + apn="" + type="ia" + /> + + <apn carrier="Cosmote Connect Mobile" + mcc="226" + mnc="06" + apn="broadband" + type="default,supl" + /> + + <apn carrier="Cosmote MMS" + mcc="226" + mnc="06" + apn="mms" + user="mms" + password="mms" + mmsc="http://mmsc1.mms.cosmote.ro:8002" + mmsproxy="10.252.1.62" + mmsport="8080" + type="mms" + /> + + <apn carrier="web'n'walk" + mcc="226" + mnc="06" + apn="wnw" + user="wnw" + password="wnw" + type="default,supl" + /> + + <apn carrier="Orange Internet" + carrier_id = "1011" + mcc="226" + mnc="10" + apn="" + type="ia" + /> + + <apn carrier="Orange MMS" + carrier_id = "1011" + mcc="226" + mnc="10" + apn="mms" + user="mms" + password="mms" + mmsc="http://wap.mms.orange.ro:8002" + mmsproxy="62.217.247.252" + mmsport="8799" + authtype="1" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "1011" + mcc="226" + mnc="10" + apn="net" + type="default" + /> + + <apn carrier="Swisscom MMS" + carrier_id = "2366" + mcc="228" + mnc="01" + apn="event.swisscom.ch" + mmsc="http://mms.natel.ch:8079" + mmsproxy="192.168.210.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Swisscom Services" + carrier_id = "2366" + mcc="228" + mnc="01" + apn="gprs.swisscom.ch" + proxy="192.168.210.1" + port="8080" + type="default,supl" + /> + + <apn carrier="Sunrise live" + carrier_id = "1413" + mcc="228" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Sunrise MMS" + carrier_id = "1413" + mcc="228" + mnc="02" + apn="mms.sunrise.ch" + mmsc="http://mmsc.sunrise.ch" + mmsproxy="212.35.34.75" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "1414" + mcc="228" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "1414" + mcc="228" + mnc="03" + apn="mms" + mmsc="http://192.168.151.3:8002" + mmsproxy="192.168.151.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="228" + mnc="03" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="CH-Transatel" + mvno_type="spn" + /> + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="228" + mnc="03" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="BB00" + mvno_type="gid" + /> + + <apn carrier="T-Mobile CZ" + carrier_id = "2394" + mcc="230" + mnc="01" + apn="" + type="ia" + protocol="IPV4V6" + /> + + <apn carrier="T-Mobile IMS" + carrier_id = "2394" + mcc="230" + mnc="01" + apn="IMS" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="T-Mobile CZ" + carrier_id = "2394" + mcc="230" + mnc="01" + apn="internet.t-mobile.cz" + user="wap" + password="wap" + authtype="1" + type="default,supl" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2394" + mcc="230" + mnc="01" + apn="mms.t-mobile.cz" + user="mms" + password="mms" + mmsc="http://mms" + mmsproxy="10.0.0.10" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="O2 internet" + carrier_id = "1449" + mcc="230" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="O2 MMS" + carrier_id = "1449" + mcc="230" + mnc="02" + apn="mms" + mmsc="http://mms.o2active.cz:8002" + mmsproxy="160.218.160.218" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "2398" + mcc="230" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "2398" + mcc="230" + mnc="03" + apn="mms" + user="mms" + password="mms" + mmsc="http://mms" + mmsproxy="10.11.10.111" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Orange SK" + carrier_id = "1713" + mcc="231" + mnc="01" + apn="internet" + type="default" + /> + + <apn carrier="Orange SK MMS" + carrier_id = "1713" + mcc="231" + mnc="01" + apn="mms" + user="wap" + password="wap" + authtype="1" + mmsc="http://imms.orange.sk" + mmsproxy="213.151.208.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Orange World" + carrier_id = "1713" + mcc="231" + mnc="01" + apn="orangewap" + user="wap" + password="wap" + authtype="1" + proxy="213.151.208.156" + port="8799" + type="default,supl" + /> + + <apn carrier="T-Mobile internet" + carrier_id = "2385" + mcc="231" + mnc="02" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2385" + mcc="231" + mnc="02" + apn="mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms" + mmsproxy="192.168.1.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="O2 internet" + carrier_id = "1988" + mcc="231" + mnc="06" + apn="o2internet" + type="default,supl" + /> + + <apn carrier="O2 MMS" + carrier_id = "1988" + mcc="231" + mnc="06" + apn="o2mms" + mmsc="http://mms.o2world.sk:8002" + mmsproxy="10.97.1.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="live!" + mcc="232" + mnc="01" + apn="a1.net" + user="ppp@a1plus.at" + password="ppp" + authtype="1" + type="default,supl" + /> + + <apn carrier="A1 MMS" + mcc="232" + mnc="01" + apn="free.a1.net" + user="ppp@a1plus.at" + password="ppp" + mmsc="http://mmsc.a1.net" + mmsproxy="194.48.124.71" + mmsport="8001" + authtype="1" + type="mms" + /> + + <apn carrier="T-Mobile Internet" + mcc="232" + mnc="03" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile LTE" + mcc="232" + mnc="03" + apn="internet.t-mobile.at" + user="t-mobile" + password="tm" + authtype="1" + type="default,supl" + /> + + <apn carrier="T-Mobile MMS" + mcc="232" + mnc="03" + apn="gprsmms" + user="t-mobile" + password="tm" + mmsc="http://mmsc.t-mobile.at/servlets/mms" + mmsproxy="10.12.0.20" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Planet 3" + carrier_id = "1344" + mcc="232" + mnc="05" + apn="drei.at" + mmsc="http://mmsc" + mmsproxy="213.94.78.133" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="tele.ring mms" + mcc="232" + mnc="07" + apn="mms" + user="wap@telering.at" + password="wap" + mmsc="http://relay.mms.telering.at" + mmsproxy="212.95.31.50" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="tele.ring web" + mcc="232" + mnc="07" + apn="web" + user="web@telering.at" + password="web" + authtype="1" + type="default,supl" + /> + + <apn carrier="Planet3" + carrier_id = "1344" + mcc="232" + mnc="10" + apn="drei.at" + mmsc="http://mmsc" + mmsproxy="213.94.78.133" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="data.bob" + mcc="232" + mnc="11" + apn="bob.at" + user="data@bob.at" + password="ppp" + authtype="1" + type="default,supl" + /> + + <apn carrier="data.bob MMS" + mcc="232" + mnc="11" + apn="mms.bob.at" + user="data@bob.at" + password="ppp" + mmsc="http://mmsc.bob.at" + mmsproxy="194.48.124.7" + mmsport="8001" + authtype="1" + type="mms" + /> + + <apn carrier="yesss!" + mcc="232" + mnc="12" + apn="web.yesss.at" + type="default,supl" + /> + + <apn carrier="Plintron" + mcc="232" + mnc="22" + apn="data.plintron.at" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Plintron" + /> + + <apn carrier="UBIQUISYS" + carrier_id = "1491" + mcc="234" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="O2 MOBILE WEB" + carrier_id = "1492" + mcc="234" + mnc="02" + apn="mobile.o2.co.uk" + user="O2web" + password="O2web" + type="default,supl" + /> + + <apn carrier="O2 MMS Prepay" + carrier_id = "1492" + mcc="234" + mnc="02" + apn="payandgo.o2.co.uk" + user="payandgo" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="O2 MMS Postpay" + carrier_id = "1492" + mcc="234" + mnc="02" + apn="wap.o2.co.uk" + user="o2wap" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="BT One Phone Internet" + carrier_id = "2103" + mcc="234" + mnc="08" + apn="internet.btonephone.com" + mvno_type="gid" + mvno_match_data="B2" + type="default,supl" + /> + + <apn carrier="BT One Phone MMS" + carrier_id = "2103" + mcc="234" + mnc="08" + apn="mms.btonephone.com" + mmsc="http://MMSC/" + mmsproxy="proxy.btonephone.com" + mmsport="8080" + mvno_type="gid" + mvno_match_data="B2" + type="mms" + /> + + <apn carrier="O2 Mobile Web" + carrier_id = "1492" + mcc="234" + mnc="10" + apn="mobile.o2.co.uk" + user="o2web" + password="password" + type="default,supl" + /> + + <apn carrier="O2 MMS" + carrier_id = "1492" + mcc="234" + mnc="10" + apn="wap.o2.co.uk" + user="o2wap" + password="password" + authtype="1" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="O2 Pay & Go" + carrier_id = "1492" + mcc="234" + mnc="10" + apn="payandgo.o2.co.uk" + proxy="82.132.254.1" + port="8080" + user="payandgo" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="TESCO" + carrier_id = "2093" + mcc="234" + mnc="10" + apn="prepay.tesco-mobile.com" + proxy="193.113.200.195" + port="8080" + user="tescowap" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="193.113.200.195" + mmsport="8080" + authtype="1" + type="default,supl,mms" + mvno_match_data="0A" + mvno_type="gid" + /> + + <apn carrier="giffgaff" + carrier_id = "2118" + mcc="234" + mnc="10" + apn="giffgaff.com" + authtype="1" + user="giffgaff" + password="password" + mmsc="http://mmsc.mediamessaging.co.uk:8002" + mmsproxy="193.113.200.195" + mmsport="8080" + mvno_type="spn" + mvno_match_data="giffgaff" + /> + + <apn carrier="Jump UK" + carrier_id = "2138" + mcc="234" + mnc="10" + apn="mobiledata" + authtype="0" + mvno_type="spn" + mvno_match_data="Jump" + /> + + <apn carrier="O2 MOBILE WEB" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="mobile.o2.co.uk" + user="O2web" + password="O2web" + type="default,supl" + /> + + <apn carrier="O2 MMS Prepay" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="payandgo.o2.co.uk" + user="payandgo" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="O2 MMS Postpay" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="wap.o2.co.uk" + user="o2wap" + password="password" + mmsc="http://mmsc.mms.o2.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + + <apn carrier="O2 MOBILE WEB" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="mobile.o2.co.uk" + user="O2web" + password="O2web" + type="default,supl" + /> + + <apn carrier="O2 MMS Prepay" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="payandgo.o2.co.uk" + user="payandgo" + password="password" + mmsc="http://mmsc.mms.02.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="O2 MMS Postpay" + carrier_id = "1492" + mcc="234" + mnc="11" + apn="wap.o2.co.uk" + user="o2wap" + password="password" + mmsc="http://mmsc.mms.02.co.uk:8002" + mmsproxy="82.132.254.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone UK" + mcc="234" + mnc="15" + apn="wap.vodafone.co.uk" + user="wap" + password="wap" + mmsc="http://mms.vodafone.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + authtype="1" + type="default,supl,mms" + user_editable="false" + /> + + <apn carrier="Vodafone UK Prepay" + mcc="234" + mnc="15" + apn="pp.vodafone.co.uk" + user="wap" + password="wap" + mmsc="http://mms.vodafone.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + authtype="1" + type="default,supl,mms" + user_editable="false" + /> + + <apn carrier="ASDA WAP" + mcc="234" + mnc="15" + apn="asdamobiles.co.uk" + proxy="212.183.137.12" + port="8799" + user="wap" + password="wap" + mmsc="http://mms.asdamobiles.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + authtype="1" + type="default,supl,mms" + mvno_match_data="A0" + mvno_type="gid" + /> + + <apn carrier="Talkmob PAYG WAP" + mcc="234" + mnc="15" + apn="payg.talkmobile.co.uk" + proxy="212.183.137.12" + port="8799" + user="wap" + password="wap" + mmsc="http://mms.talkmobile.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + authtype="1" + type="default,supl,mms" + mvno_match_data="C1" + mvno_type="gid" + /> + + <apn carrier="Talkmob WAP" + mcc="234" + mnc="15" + apn="talkmobile.co.uk" + proxy="212.183.137.12" + port="8799" + user="wap" + password="wap" + mmsc="http://mms.talkmobile.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + authtype="1" + type="default,supl,mms" + mvno_match_data="C1" + mvno_type="gid" + /> + + <apn carrier="TalkTalk WAP" + mcc="234" + mnc="15" + apn="mobile.talktalk.co.uk" + mmsc="http://mms.talktalk.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + type="default,supl,mms" + mvno_match_data="70" + mvno_type="gid" + /> + + <apn carrier="Sainsbury's PAYG" + carrier_id = "2308" + mcc="234" + mnc="15" + apn="payg.mobilebysainsburys.co.uk" + authtype="1" + mmsc="http://mms.mobilebysainsburys.co.uk/servlets/mms" + mmsproxy="212.183.137.12" + mmsport="8799" + mvno_type="spn" + mvno_match_data="Sainsbury's" + /> + + <apn carrier="Lebara Internet" + carrier_id = "2309" + mcc="234" + mnc="15" + apn="uk.lebara.mobi" + authtype="1" + user="wap" + password="wap" + mmsc="http://mms.lebara.co.uk/servlets/mms" + mmsproxy="212.183.137.012" + mmsport="8799" + mvno_type="spn" + mvno_match_data="Lebara" + type="default,supl,mms" + /> + + <apn carrier="3" + carrier_id = "1505" + mcc="234" + mnc="20" + apn="three.co.uk" + mmsc="http://mms.um.three.co.uk:10021/mmsc" + mmsproxy="mms.three.co.uk" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="3 Hotspot" + carrier_id = "1505" + mcc="234" + mnc="20" + apn="3hotspot" + authtype="0" + type="dun" + /> + + <apn carrier="Lycamobile" + carrier_id = "2152" + mcc="234" + mnc="26" + apn="data.lycamobile.co.uk" + authtype="1" + user="lmuk" + password="plus" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Virgin Media Mobile Internet" + carrier_id = "717" + mcc="234" + mnc="30" + apn="goto.virginmobile.uk" + user="user" + mmsc="http://mms.virginmobile.co.uk:8002" + mmsproxy="193.30.166.2" + mmsport="8080" + authtype="1" + type="default,supl,mms" + mvno_match_data="28" + mvno_type="gid" + /> + + <apn carrier="EE Internet" + carrier_id = "718" + mcc="234" + mnc="30" + apn="everywhere" + user="eesecure" + password="secure" + authtype="1" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="EE MMS" + carrier_id = "718" + mcc="234" + mnc="30" + apn="eezone" + user="eesecure" + password="secure" + mmsc="http://mms/" + mmsproxy="149.254.201.135" + mmsport="8080" + authtype="1" + type="mms" + protocol="IPV4" + /> + + <apn carrier="EE Emergency" + carrier_id = "718" + mcc="234" + mnc="30" + apn="SOS" + authtype="1" + type="Emergency" + protocol="IPV6" + /> + + <apn carrier="EE IMS" + carrier_id = "718" + mcc="234" + mnc="30" + apn="ims" + authtype="1" + type="ims" + protocol="IPV6" + roaming_protocol="IPV6" + /> + + <apn carrier="BT One Phone Internet" + carrier_id = "2103" + mcc="234" + mnc="30" + apn="internet.btonephone.com" + mvno_type="gid" + mvno_match_data="B2" + type="default,supl" + /> + + <apn carrier="BT One Phone MMS" + carrier_id = "2103" + mcc="234" + mnc="30" + apn="mms.btonephone.com" + mmsc="http://MMSC/" + mmsproxy="proxy.btonephone.com" + mmsport="8080" + mvno_type="gid" + mvno_match_data="B2" + type="mms" + /> + + <apn carrier="BT Internet" + carrier_id = "2102" + mcc="234" + mnc="30" + apn="everywhere" + user="eesecure" + password="secure" + authtype="1" + mvno_type="gid" + mvno_match_data="B3" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="BT MMS" + carrier_id = "2102" + mcc="234" + mnc="30" + apn="eezone" + user="eesecure" + password="secure" + authtype="1" + mmsc="http://mms/" + mmsproxy="149.254.201.135" + mmsport="8080" + mvno_type="gid" + mvno_match_data="B3" + type="mms" + /> + + <apn carrier="BT Emergency" + carrier_id = "2102" + mcc="234" + mnc="30" + apn="SOS" + authtype="1" + mvno_type="gid" + mvno_match_data="B3" + type="Emergency" + protocol="IPV6" + /> + + <apn carrier="BT IMS" + carrier_id = "2102" + mcc="234" + mnc="30" + apn="ims" + authtype="1" + mvno_type="gid" + mvno_match_data="B3" + type="ims" + protocol="IPV6" + roaming_protocol="IPV6" + /> + + <apn carrier="BT Internet" + carrier_id = "2101" + mcc="234" + mnc="30" + apn="everywhere" + user="eesecure" + password="secure" + authtype="1" + mvno_type="gid" + mvno_match_data="C3" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="BT MMS" + carrier_id = "2101" + mcc="234" + mnc="30" + apn="eezone" + user="eesecure" + password="secure" + authtype="1" + mmsc="http://mms/" + mmsproxy="149.254.201.135" + mmsport="8080" + mvno_type="gid" + mvno_match_data="C3" + type="mms" + /> + + <apn carrier="BT Emergency" + carrier_id = "2101" + mcc="234" + mnc="30" + apn="SOS" + authtype="1" + mvno_type="gid" + mvno_match_data="C3" + type="Emergency" + protocol="IPV6" + /> + + <apn carrier="BT IMS" + carrier_id = "2101" + mcc="234" + mnc="30" + apn="ims" + authtype="1" + mvno_type="gid" + mvno_match_data="C3" + type="ims" + protocol="IPV6" + roaming_protocol="IPV6" + /> + + <apn carrier="Internet" + carrier_id = "2283" + mcc="234" + mnc="33" + apn="tslpaygnet" + authtype="0" + type="default,supl,agps,fota,dun" + mvno_type="spn" + mvno_match_data="LIFE" + /> + + <apn carrier="MMS" + carrier_id = "2283" + mcc="234" + mnc="33" + apn="tslmms" + authtype="1" + user="wap" + password="wap" + mmsc="http://mms/" + mmsproxy="193.35.133.194" + mmsport="8080" + type="mms" + mvno_type="spn" + mvno_match_data="LIFE" + /> + + <apn carrier="EE Internet" + carrier_id = "718" + mcc="234" + mnc="33" + apn="everywhere" + user="eesecure" + password="secure" + authtype="1" + type="default,supl" + /> + + <apn carrier="EE MMS" + carrier_id = "718" + mcc="234" + mnc="33" + apn="eezone" + user="eesecure" + password="secure" + mmsc="http://mms/" + mmsproxy="149.254.201.135" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="EE Emergency" + carrier_id = "718" + mcc="234" + mnc="33" + apn="SOS" + authtype="1" + type="Emergency" + protocol="IPV6" + /> + + <apn carrier="EE IMS" + carrier_id = "718" + mcc="234" + mnc="33" + apn="ims" + authtype="1" + type="ims" + protocol="IPV6" + roaming_protocol="IPV6" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="234" + mnc="25" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Jump" + carrier_id = "2138" + mcc="234" + mnc="39" + apn="Jump" + mmsc="http://mmsc.mobi/servlets/mms" + mmsproxy="164.39.236.69" + mmsport="80" + protocol="IP" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="Jump" + /> + + <apn carrier="Gamma Data" + carrier_id = "2137" + mcc="234" + mnc="39" + apn="gamma.co.uk" + mmsc="http://mms.gamma.co.uk/servlets/mms" + mmsproxy="164.39.236.69" + mmsport="80" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="EMnify" + carrier_id = "2326" + mcc="234" + mnc="50" + apn="em" + mvno_match_data="234500022" + mvno_type="imsi" + type="default,supl" + /> + + <apn carrier="Jersey Telecom" + carrier_id = "1506" + mcc="234" + mnc="50" + apn="mms" + user="mms" + password="mms" + mmsc="http://mms.surfmail.com/mmsc" + mmsproxy="212.9.19.199" + mmsport="3130" + type="mms" + /> + + <apn carrier="pepperWEB (Jersey)" + carrier_id = "1506" + mcc="234" + mnc="50" + apn="pepper" + type="default,supl" + /> + + <apn carrier="C&W Guernsey Internet" + carrier_id = "720" + mcc="234" + mnc="55" + apn="internet" + type="default,supl" + /> + + <apn carrier="Sure Picture Messaging" + carrier_id = "720" + mcc="234" + mnc="55" + apn="mms" + mmsc="http://mmsc.gprs.cw.com/" + mmsproxy="10.0.3.101" + mmsport="80" + type="mms" + /> + + <apn carrier="3G HSDPA" + carrier_id = "1507" + mcc="234" + mnc="58" + apn="3gpronto" + type="default,supl" + /> + + <apn carrier="Manx Telecom Contract MMS" + carrier_id = "1507" + mcc="234" + mnc="58" + apn="mms.manxpronto.net" + user="mms" + password="mms" + mmsc="http://mms.manxpronto.net:8002" + mmsproxy="195.10.99.46" + mmsport="8080" + type="mms" + /> + + <apn carrier="Manx Telecom Prepay MMS" + carrier_id = "1507" + mcc="234" + mnc="58" + apn="mms.prontogo.net" + user="mmsgo" + password="mmsgo" + mmsc="http://mms.manxpronto.net:8002" + mmsproxy="195.10.99.41" + mmsport="8080" + type="mms" + /> + + <apn carrier="Manx Telecom Contract WEB" + carrier_id = "1507" + mcc="234" + mnc="58" + apn="web.manxpronto.net" + user="gprs" + password="gprs" + type="default,supl" + /> + + <apn carrier="EE Internet" + carrier_id = "718" + mcc="234" + mnc="86" + apn="everywhere" + user="eesecure" + password="secure" + authtype="1" + type="default,supl" + /> + + <apn carrier="EE MMS" + carrier_id = "718" + mcc="234" + mnc="86" + apn="eezone" + user="eesecure" + password="secure" + mmsc="http://mms/" + mmsproxy="149.254.201.135" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="3hotspot" + carrier_id = "1505" + mcc="235" + mnc="94" + apn="3hotspot" + authtype="0" + type="dun" + /> + + <apn carrier="3" + carrier_id = "1505" + mcc="235" + mnc="94" + apn="three.co.uk" + mmsc="http://mms.um.three.co.uk:10021/mmsc" + mmsproxy="mms.three.co.uk" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="DK TDC" + carrier_id = "1463" + mcc="238" + mnc="01" + apn="internet" + authtype="0" + type="default,supl,agps,fota,dun" + /> + + <apn carrier="DK TDC mms" + carrier_id = "1463" + mcc="238" + mnc="01" + apn="mms" + authtype="0" + mmsc="http://192.168.241.114:8002" + mmsproxy="194.182.251.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="TDC Internet" + mcc="238" + mnc="01" + apn="internet" + type="default,supl" + mvno_match_data="2380101xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="TDC MMS" + mcc="238" + mnc="01" + apn="mms" + mmsc="http://mmsc.tdc.dk:8002" + mmsproxy="194.182.251.15" + mmsport="8080" + type="mms" + mvno_match_data="2380101xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Telmore Internet" + carrier_id = "2284" + mcc="238" + mnc="01" + apn="internet" + type="default,supl" + mvno_type="spn" + mvno_match_data="TELMORE" + /> + + <apn carrier="Telmore MMS" + carrier_id = "2284" + mcc="238" + mnc="01" + apn="mms" + mmsproxy="194.182.251.15" + mmsport="8080" + mmsc="http://192.168.241.114:8002" + type="mms" + mvno_type="spn" + mvno_match_data="TELMORE" + /> + + <apn carrier="TELMORE WAP" + carrier_id = "2284" + mcc="238" + mnc="01" + apn="wap" + proxy="194.182.251.15" + port="8080" + authtype="0" + type="default" + mvno_type="spn" + mvno_match_data="TELMORE" + /> + + <apn carrier="GigSky" + carrier_id="2459" + mcc="238" + mnc="01" + apn="gigsky" + type="default" + mvno_type="spn" + mvno_match_data="GigSky" + /> + + <apn carrier="Telenor Internet" + carrier_id = "1464" + mcc="238" + mnc="02" + apn="Internet" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1464" + mcc="238" + mnc="02" + apn="telenor" + mmsc="http://mms.telenor.dk" + mmsproxy="212.88.64.8" + mmsport="8080" + type="mms" + /> + + <apn carrier="3" + carrier_id = "1466" + mcc="238" + mnc="06" + apn="data.tre.dk" + mmsc="http://mms.3.dk/" + mmsproxy="mmsproxy.3.dk" + mmsport="8799" + type="default,supl,mms" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Telia SurfPort" + carrier_id = "656" + mcc="238" + mnc="20" + apn="www.internet.mtelia.dk" + type="default,supl" + /> + + <apn carrier="Telia MMS" + carrier_id = "656" + mcc="238" + mnc="20" + apn="www.mms.mtelia.dk" + mmsc="http://mms.telia.dk" + mmsproxy="193.209.134.131" + mmsport="8080" + type="mms" + /> + + <apn carrier="Call me Internet" + carrier_id = "2285" + mcc="238" + mnc="20" + apn="webSP" + type="default,supl" + mvno_type="spn" + mvno_match_data="Call me" + /> + + <apn carrier="Call me MMS" + carrier_id = "2285" + mcc="238" + mnc="20" + apn="mmsSP" + mmsproxy="193.209.134.131" + mmsport="8080" + mmsc="http://mms.telia.dk" + type="mms" + mvno_type="spn" + mvno_match_data="Call me" + /> + + <apn carrier="DLG Tele GPRS" + carrier_id = "2286" + mcc="238" + mnc="20" + apn="webSP" + type="default,supl" + mvno_type="spn" + mvno_match_data="DLG Tele" + /> + + <apn carrier="DLG Tele MMS" + carrier_id = "2286" + mcc="238" + mnc="20" + apn="mmsSP" + mmsproxy="193.209.134.131" + mmsport="8080" + mmsc="http://mms.telia.dk" + type="mms" + mvno_type="spn" + mvno_match_data="DLG Tele" + /> + + <apn carrier="Orange DE" + carrier_id = "656" + mcc="238" + mnc="30" + apn="web.orange.dk" + user="" + password="" + /> + + <apn carrier="Telenor Internet" + carrier_id = "657" + mcc="238" + mnc="77" + apn="Internet" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "657" + mcc="238" + mnc="77" + apn="telenor" + mmsc="http://mms.telenor.dk" + mmsproxy="212.88.64.8" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telia MMS" + carrier_id = "1690" + mcc="240" + mnc="01" + apn="mms.telia.se" + mmsc="http://mmss" + mmsproxy="193.209.134.132" + mmsport="80" + type="mms" + /> + + <apn carrier="Telia" + carrier_id = "1690" + mcc="240" + mnc="01" + apn="online.telia.se" + type="default,supl" + /> + + <apn carrier="Halebop Internet" + carrier_id = "2287" + mcc="240" + mnc="01" + apn="halebop.telia.se" + type="default,supl" + mvno_match_data="240017xxxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Halebop MMS" + carrier_id = "2287" + mcc="240" + mnc="01" + apn="mms.telia.se" + mmsc="http://mmss" + mmsproxy="193.209.134.132" + mmsport="80" + type="mms" + mvno_match_data="240017xxxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="3" + carrier_id = "1691" + mcc="240" + mnc="02" + apn="data.tre.se" + mmsc="http://mms.tre.se" + mmsproxy="mmsproxy.tre.se" + mmsport="8799" + type="default,supl,mms" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="3" + carrier_id = "1693" + mcc="240" + mnc="04" + apn="data.tre.se" + mmsc="http://mms.tre.se" + mmsproxy="mmsproxy.tre.se" + mmsport="8799" + type="default,supl,mms" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Tele2 Internet" + mcc="240" + mnc="05" + apn="4g.tele2.se" + type="default,supl" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 MMS" + mcc="240" + mnc="05" + apn="4g.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 Internet 3G" + mcc="240" + mnc="05" + apn="internet.tele2.se" + type="default,supl" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 MMS 3G" + mcc="240" + mnc="05" + apn="internet.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Telia MMS" + carrier_id = "1690" + mcc="240" + mnc="05" + apn="mms.telia.se" + mmsc="http://mmss" + mmsproxy="193.209.134.132" + mmsport="80" + type="mms" + mvno_match_data="Telia" + mvno_type="spn" + /> + + <apn carrier="Telia" + carrier_id = "1690" + mcc="240" + mnc="05" + apn="online.telia.se" + type="default,supl" + mvno_match_data="Telia" + mvno_type="spn" + /> + + <apn carrier="Halebop Internet" + carrier_id = "2287" + mcc="240" + mnc="05" + apn="halebop.telia.se" + type="default,supl" + mvno_match_data="Halebop" + mvno_type="spn" + /> + + <apn carrier="Halebop MMS" + carrier_id = "2287" + mcc="240" + mnc="05" + apn="mms.telia.se" + mmsc="http://mmss" + mmsproxy="193.209.134.132" + mmsport="80" + type="mms" + mvno_match_data="Halebop" + mvno_type="spn" + /> + + <apn carrier="Internet" + carrier_id = "1695" + mcc="240" + mnc="06" + apn="internet" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1695" + mcc="240" + mnc="06" + apn="mms" + mmsc="http://mms.media" + type="mms" + /> + + <apn carrier="Tele2 Internet" + carrier_id = "1696" + mcc="240" + mnc="07" + apn="4g.tele2.se" + type="default,supl" + /> + + <apn carrier="Tele2 MMS" + carrier_id = "1696" + mcc="240" + mnc="07" + apn="4g.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + /> + + <apn carrier="Tele2 Internet 3G" + carrier_id = "1696" + mcc="240" + mnc="07" + apn="internet.tele2.se" + type="default,supl" + /> + + <apn carrier="Tele2 MMS 3G" + carrier_id = "1696" + mcc="240" + mnc="07" + apn="internet.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + /> + + <apn carrier="Tele2 Internet" + mcc="240" + mnc="07" + apn="internet.tele2.no" + user="wap" + password="wap" + type="default,supl" + authtype="1" + mvno_match_data="2400768xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Tele2 MMS" + mcc="240" + mnc="07" + apn="internet.tele2.no" + mmsproxy="193.12.40.14" + mmsport="8080" + mmsc="http://mmsc.tele2.no" + type="mms" + mvno_match_data="2400768xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Jump" + carrier_id = "2138" + mcc="240" + mnc="07" + apn="Jump" + mmsc="http://mmsc.mobi/servlets/mms" + mmsproxy="164.39.236.69" + mmsport="80" + protocol="IP" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="Jump" + /> + + <apn carrier="Gamma Data" + carrier_id = "2137" + mcc="240" + mnc="07" + apn="gamma.co.uk" + mmsc="http://mms.gamma.co.uk/servlets/mms" + mmsproxy="164.39.236.69" + mmsport="80" + protocol="IP" + roaming_protocol="IP" + mvno_type="imsi" + mvno_match_data="240075610" + /> + + <apn carrier="GigSky" + carrier_id="2459" + mcc="240" + mnc="07" + apn="gigsky" + type="default" + mvno_type="spn" + mvno_match_data="GigSky" + /> + + <apn carrier="Telenor Mobilsurf" + carrier_id = "1695" + mcc="240" + mnc="08" + apn="services.telenor.se" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1695" + mcc="240" + mnc="08" + apn="mms" + mmsc="http://mms" + mmsproxy="172.30.253.241" + mmsport="8799" + type="mms" + /> + + <apn carrier="Com4" + carrier_id = "1956" + mcc="240" + mnc="09" + apn="com4" + type="default,supl" + /> + + <apn carrier="Spring data" + carrier_id = "1697" + mcc="240" + mnc="10" + apn="data.springmobil.se" + type="default,supl" + /> + + <apn carrier="Spring MMS" + carrier_id = "1697" + mcc="240" + mnc="10" + apn="mms.springmobil.se" + mmsc="http://mms.springmobil.se" + mmsproxy="213.88.184.37" + mmsport="8080" + type="mms" + /> + + <apn carrier="Halebop Internet" + mcc="240" + mnc="017" + apn="halebop.telia.se" + type="default,supl" + /> + + <apn carrier="Halebop MMS" + mcc="240" + mnc="017" + apn="mms.telia.se" + user="mms" + password="telia" + mmsc="http://mmss" + mmsproxy="193.209.134.132" + mmsport="9201" + type="mms" + /> + + <apn carrier="Tele2 Internet" + carrier_id = "1696" + mcc="240" + mnc="24" + apn="4g.tele2.se" + type="default,supl" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 MMS" + carrier_id = "1696" + mcc="240" + mnc="24" + apn="4g.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 Internet 3G" + carrier_id = "1696" + mcc="240" + mnc="24" + apn="internet.tele2.se" + type="default,supl" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Tele2 MMS 3G" + carrier_id = "1696" + mcc="240" + mnc="24" + apn="internet.tele2.se" + mmsc="http://mmsc.tele2.se" + mmsproxy="130.244.202.30" + mmsport="8080" + type="mms" + mvno_match_data="Tele2" + mvno_type="spn" + /> + + <apn carrier="Ventelo Internett" + carrier_id = "2333" + mcc="242" + mnc="01" + apn="internet.ventelo.no" + type="default,supl" + mvno_match_data="24201700xxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Ventelo MMS" + carrier_id = "2333" + mcc="242" + mnc="01" + apn="mms.ventelo.no" + user="ventelo" + password="1111" + mmsc="http://mmsc/" + mmsproxy="10.10.10.11" + mmsport="8080" + type="mms" + authtype="1" + mvno_match_data="24201700xxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Telenor" + carrier_id = "958" + mcc="242" + mnc="01" + apn="telenor" + mmsc="http://mmsc" + mmsproxy="10.10.10.11" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="NetCom" + carrier_id = "959" + mcc="242" + mnc="02" + apn="netcom" + mmsc="http://mm/" + mmsproxy="212.169.66.4" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Chess MMS" + carrier_id = "2334" + mcc="242" + mnc="02" + apn="netcom" + user="mms" + password="netcom" + mmsproxy="212.169.66.4" + mmsport="8080" + mmsc="http://mm/" + type="mms" + authtype="1" + mvno_match_data="2420256xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Chess Internett" + carrier_id = "2334" + mcc="242" + mnc="02" + apn="netcom" + type="default,supl" + mvno_match_data="2420256xxxxxxxx" + mvno_type="imsi" + /> + + <apn carrier="Tele2 Internet" + carrier_id = "961" + mcc="242" + mnc="04" + apn="internet.tele2.no" + mmsc="http://mmsc.tele2.no" + mmsproxy="193.12.40.14" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="NwN Internet" + carrier_id = "1900" + mcc="242" + mnc="05" + apn="internet" + type="default,supl" + /> + + <apn carrier="NwN MMS" + carrier_id = "1900" + mcc="242" + mnc="05" + apn="mms" + mmsc="http://mms.nwn.no" + mmsproxy="188.149.250.10" + mmsport="80" + type="mms" + /> + + <apn carrier="Com4" + carrier_id = "2134" + mcc="242" + mnc="09" + apn="com4" + type="default,supl" + /> + + <apn carrier="DNA Internet" + carrier_id = "1904" + mcc="244" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="DNA MMS" + carrier_id = "1904" + mcc="244" + mnc="03" + apn="mms" + mmsc="http://mmsc.dna.fi" + mmsproxy="10.1.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="DNA Internet" + carrier_id = "682" + mcc="244" + mnc="04" + apn="internet" + type="default,supl" + /> + + <apn carrier="DNA MMS" + carrier_id = "682" + mcc="244" + mnc="04" + apn="mms" + user="dna" + password="mms" + mmsc="http://mmsc.dnafinland.fi/" + mmsproxy="10.1.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Elisa Internet" + carrier_id = "1475" + mcc="244" + mnc="05" + apn="internet" + type="default,supl" + /> + + <apn carrier="Elisa MMS" + carrier_id = "1475" + mcc="244" + mnc="05" + apn="mms" + mmsc="http://mms.elisa.fi" + mmsproxy="213.161.41.57" + mmsport="80" + type="mms" + /> + + <apn carrier="Saunalahti Internet" + carrier_id = "1479" + mcc="244" + mnc="05" + apn="internet.saunalahti" + type="default,supl" + mvno_match_data="2440541" + mvno_type="imsi" + /> + + <apn carrier="Saunalahti MMS" + carrier_id = "1479" + mcc="244" + mnc="05" + apn="mms.saunalahti.fi" + mmsc="http://mms.saunalahti.fi:8002/" + mmsproxy="62.142.4.197" + mmsport="8080" + type="mms" + mvno_match_data="2440541" + mvno_type="imsi" + /> + + <apn carrier="TDC Internet" + carrier_id = "1907" + mcc="244" + mnc="10" + apn="internet.song.fi" + user="song@internet" + password="songnet" + type="default,supl" + /> + + <apn carrier="TDC MMS" + carrier_id = "1907" + mcc="244" + mnc="10" + apn="mms.song.fi" + mmsc="http://mms.song.fi" + mmsproxy="213.161.41.58" + mmsport="80" + type="mms" + /> + + <apn carrier="DNA Internet" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="internet" + type="default,supl" + /> + + <apn carrier="DNA MMS" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="mms" + mmsc="http://mmsc.dna.fi" + mmsproxy="10.1.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="DNA Pro Internet" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="dnapro.fi" + authtype="1" + type="default,supl" + /> + + <apn carrier="DNA Pro MMS" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="mms.dnapro.fi" + mmsc="http://mmsc.dnapro.fi/" + mmsproxy="10.1.1.21" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="TDC Internet Finland" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="inet.tdc.fi" + authtype="1" + type="default,supl" + /> + + <apn carrier="TDC MMS Finland" + carrier_id = "1904" + mcc="244" + mnc="12" + apn="mms.tdc.fi" + mmsc="http://mmsc.tdc.fi" + mmsproxy="10.1.12.2" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="DNA Internet" + carrier_id = "1904" + mcc="244" + mnc="13" + apn="internet" + type="default,supl" + /> + + <apn carrier="DNA MMS" + carrier_id = "1904" + mcc="244" + mnc="13" + apn="mms" + user="dna" + password="mms" + mmsc="http://mmsc.dnafinland.fi/" + mmsproxy="10.1.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Saunalahti Internet" + carrier_id = "1479" + mcc="244" + mnc="21" + apn="internet.saunalahti" + type="default,supl" + /> + + <apn carrier="Saunalahti MMS" + carrier_id = "1479" + mcc="244" + mnc="21" + apn="mms.saunalahti.fi" + mmsc="http://mms.saunalahti.fi:8002/" + mmsproxy="62.142.4.197" + mmsport="8080" + type="mms" + /> + + <apn carrier="SONERA Internet" + carrier_id = "1480" + mcc="244" + mnc="91" + apn="internet" + type="default,supl" + /> + + <apn carrier="SONERA MMS" + carrier_id = "1480" + mcc="244" + mnc="91" + apn="wap.sonera.net" + mmsc="http://mms.sonera.fi:8002" + mmsproxy="195.156.25.33" + mmsport="80" + type="mms" + /> + + <apn carrier="Omnitel MMS" + carrier_id = "892" + mcc="246" + mnc="01" + apn="gprs.mms.lt" + user="mms" + password="mms" + mmsc="http://mms.omnitel.net:8002/" + mmsproxy="194.176.32.149" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Omnitel Internet" + carrier_id = "892" + mcc="246" + mnc="01" + apn="omnitel" + user="omni" + password="omni" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bite Internet" + carrier_id = "893" + mcc="246" + mnc="02" + apn="wap" + type="default,supl" + /> + + <apn carrier="Bite MMS" + carrier_id = "893" + mcc="246" + mnc="02" + apn="mms" + user="mms@mms" + password="mms" + mmsc="http://mmsc/servlets/mms" + mmsproxy="192.168.150.2" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Tele2 Internet LT" + carrier_id = "894" + mcc="246" + mnc="03" + apn="internet.tele2.lt" + mmsc="http://mmsc.tele2.lt/" + mmsproxy="193.12.40.29" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Test FOTA" + mcc="246" + mnc="081" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Test FOTA" + mcc="246" + mnc="081" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Test CBS" + mcc="246" + mnc="081" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Test CBS" + mcc="246" + mnc="081" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Test IMS" + mcc="246" + mnc="081" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Test IMS" + mcc="246" + mnc="081" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="081" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + authtype="3" + bearer_bitmask="6" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="081" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="081" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test FOTA" + mcc="246" + mnc="81" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test FOTA" + mcc="246" + mnc="81" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test CBS" + mcc="246" + mnc="81" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test CBS" + mcc="246" + mnc="81" + apn="VZWAPP" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test IMS" + mcc="246" + mnc="81" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test IMS" + mcc="246" + mnc="81" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="81" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + authtype="3" + bearer_bitmask="6" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="81" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Test Internet" + mcc="246" + mnc="81" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="LMT Internet" + carrier_id = "898" + mcc="247" + mnc="01" + apn="internet.lmt.lv" + type="default,supl" + /> + + <apn carrier="LMT MMS" + carrier_id = "898" + mcc="247" + mnc="01" + apn="internet.lmt.lv" + mmsc="http://mmsc.lmt.lv/mmsc" + type="mms" + /> + + <apn carrier="Tele2 LV Internet" + carrier_id = "899" + mcc="247" + mnc="02" + apn="internet.tele2.lv" + type="default,supl" + /> + + <apn carrier="Tele2 LV MMS" + carrier_id = "899" + mcc="247" + mnc="02" + apn="mms.tele2.lv" + user="wap" + password="wap" + mmsc="http://mmsc.tele2.lv/" + mmsproxy="193.12.40.38" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Bite LV Internet" + carrier_id = "2037" + mcc="247" + mnc="05" + apn="internet" + type="default,supl" + /> + + <apn carrier="Bite LV MMS" + carrier_id = "2037" + mcc="247" + mnc="05" + apn="mms" + user="mms@mms" + password="mms" + mmsc="http://mmsc/servlets/mms" + mmsproxy="192.168.150.2" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Bite LV WAP" + carrier_id = "2037" + mcc="247" + mnc="05" + apn="wap" + proxy="213.226.131.133" + port="8080" + type="default,supl" + /> + + <apn carrier="EMT Internet" + carrier_id = "667" + mcc="248" + mnc="01" + apn="internet.emt.ee" + type="default,supl" + /> + + <apn carrier="EMT MMS" + carrier_id = "667" + mcc="248" + mnc="01" + apn="mms.emt.ee" + mmsc="http://mms.emt.ee/servlets/mms" + mmsproxy="217.71.32.82" + mmsport="8080" + type="mms" + /> + + <apn carrier="EMT WAP" + carrier_id = "667" + mcc="248" + mnc="01" + apn="wap.emt.ee" + proxy="217.71.32.236" + port="8080" + type="default,supl" + /> + + <apn carrier="Send" + carrier_id = "2332" + mcc="248" + mnc="01" + apn="send.ee" + mmsc="http://mms.emt.ee/servlets/mms" + mmsproxy="217.71.32.82" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="248010x2" + mvno_type="imsi" + /> + + <apn carrier="Send" + carrier_id = "2332" + mcc="248" + mnc="01" + apn="send.ee" + mmsc="http://mms.emt.ee/servlets/mms" + mmsproxy="217.71.32.82" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="248010x3" + mvno_type="imsi" + /> + + <apn carrier="Elisa Internet" + carrier_id = "668" + mcc="248" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Elisa MMS" + carrier_id = "668" + mcc="248" + mnc="02" + apn="mms" + mmsc="http://194.204.2.10" + mmsproxy="194.204.2.6" + mmsport="8000" + type="mms" + /> + + <apn carrier="Elisa WAP" + carrier_id = "668" + mcc="248" + mnc="02" + apn="wap" + proxy="194.204.2.6" + port="8000" + type="default,supl" + /> + + <apn carrier="Tele2 Internet" + carrier_id = "669" + mcc="248" + mnc="03" + apn="internet.tele2.ee" + type="default,supl" + /> + + <apn carrier="Tele2 MMS" + carrier_id = "669" + mcc="248" + mnc="03" + apn="mms.tele2.ee" + mmsc="http://mmsc.tele2.ee" + mmsproxy="193.12.40.6" + mmsport="8080" + type="mms" + /> + + <apn carrier="Smart/Ultra MMS" + carrier_id = "669" + mcc="248" + mnc="03" + apn="internet.tele2.ee" + mmsc="http://mmsc.tele2.ee" + mmsproxy="193.12.40.6" + mmsport="8080" + type="mms" + /> + + <apn carrier="MTS Internet" + carrier_id = "1678" + mcc="250" + mnc="01" + apn="internet.mts.ru" + user="mts" + password="mts" + authtype="1" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="MTS MMS" + carrier_id = "1678" + mcc="250" + mnc="01" + apn="mms.mts.ru" + user="mts" + password="mts" + mmsc="http://mmsc" + mmsproxy="192.168.192.192" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Megafon Internet" + carrier_id = "1016" + mcc="250" + mnc="02" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Megafon MMS" + carrier_id = "1016" + mcc="250" + mnc="02" + apn="mms" + user="mms" + password="mms" + mmsc="http://mmsc:8002" + mmsproxy="10.10.10.10" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="YOTA Internet" + carrier_id = "1022" + mcc="250" + mnc="11" + apn="yota.ru" + type="default,supl" + /> + + <apn carrier="TELE2 Internet" + carrier_id = "1028" + mcc="250" + mnc="20" + apn="internet.tele2.ru" + type="default,supl" + /> + + <apn carrier="TELE2 MMS" + carrier_id = "1028" + mcc="250" + mnc="20" + apn="mms.tele2.ru" + mmsc="http://mmsc.tele2.ru" + mmsproxy="193.12.40.65" + mmsport="8080" + type="mms" + /> + + <apn carrier="VTB Mobile" + carrier_id = "2448" + mcc="250" + mnc="26" + apn="vtb" + user="" + password="" + type="default,supl" + /> + + <apn carrier="VODA internet" + carrier_id = "1029" + mcc="250" + mnc="28" + apn="vodalte.ru" + type="default,supl" + /> + + <apn carrier="Next Mobile" + carrier_id="2444" + mcc="250" + mnc="47" + apn="Next" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Tinkoff Mobile" + carrier_id = "2142" + mcc="250" + mnc="62" + apn="m.tinkoff" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Beeline Internet" + carrier_id = "1681" + mcc="250" + mnc="99" + apn="internet.beeline.ru" + user="beeline" + password="beeline" + authtype="1" + type="default,supl" + /> + + <apn carrier="Beeline MMS" + carrier_id = "1681" + mcc="250" + mnc="99" + apn="mms.beeline.ru" + user="beeline" + password="beeline" + mmsc="http://mms/" + mmsproxy="192.168.94.23" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="MTS MMS" + carrier_id = "1746" + mcc="255" + mnc="01" + apn="mms" + mmsc="http://mmsc:8002/" + mmsproxy="192.168.10.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="MTS-internet" + carrier_id = "1746" + mcc="255" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="Beeline-internet" + carrier_id = "12" + mcc="255" + mnc="02" + apn="internet.beeline.ua" + type="default,supl" + /> + + <apn carrier="Beeline MMS" + carrier_id = "12" + mcc="255" + mnc="02" + apn="mms.beeline.ua" + mmsc="http://mms/" + mmsproxy="172.29.18.192" + mmsport="8080" + type="mms" + /> + + + <apn carrier="Kyivstar MMS" + carrier_id = "1747" + mcc="255" + mnc="03" + apn="mms.kyivstar.net" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.kyivstar.net" + mmsproxy="10.10.10.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Kyivstar Internet" + carrier_id = "1747" + mcc="255" + mnc="03" + apn="www.kyivstar.net" + user="igprs" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Djuice MMS" + carrier_id = "2331" + mcc="255" + mnc="03" + apn="mms.djuice.com.ua" + user="djuice" + password="mms" + authtype="1" + mmsc="http://mms.kyivstar.net" + mmsproxy="10.10.10.10" + mmsport="8080" + type="mms" + mvno_match_data="DJUICE" + mvno_type="spn" + /> + + <apn carrier="Djuice Internet" + carrier_id = "2331" + mcc="255" + mnc="03" + apn="www.djuice.com.ua" + type="default,supl" + mvno_match_data="DJUICE" + mvno_type="spn" + /> + + <apn carrier="Life:) internet" + carrier_id = "1750" + mcc="255" + mnc="06" + apn="internet" + type="default,supl" + /> + + <apn carrier="Life:) MMS" + carrier_id = "1750" + mcc="255" + mnc="06" + apn="mms" + mmsc="http://mms.life.com.ua/cmmsc/post" + mmsproxy="212.58.162.230" + mmsport="8080" + type="mms" + /> + + <apn carrier="Utel Internet" + carrier_id = "1751" + mcc="255" + mnc="07" + apn="3g.utel.ua" + type="default,supl" + /> + + <apn carrier="Utel MMS" + carrier_id = "1751" + mcc="255" + mnc="07" + apn="3g.utel.ua" + mmsc="http://10.212.1.4/mms/wapenc" + mmsproxy="10.212.3.148" + mmsport="8080" + type="mms" + /> + + <apn carrier="Velcom Internet" + carrier_id = "568" + mcc="257" + mnc="01" + apn="web.velcom.by" + authtype="1" + proxy="10.200.15.15" + port="8080" + type="default,supl" + /> + + <apn carrier="Velcom MMS" + carrier_id = "568" + mcc="257" + mnc="01" + apn="mms.velcom.by" + user="mms" + password="mms" + authtype="1" + mmsc="http://mmsc" + mmsproxy="10.200.15.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="MTS Internet" + carrier_id = "569" + mcc="257" + mnc="02" + apn="mts" + user="mts" + password="mts" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTS MMS" + carrier_id = "569" + mcc="257" + mnc="02" + apn="mts" + user="mts" + password="mts" + authtype="1" + mmsc="http://mmsc" + mmsproxy="192.168.192.192" + mmsport="8080" + type="mms" + /> + + <apn carrier="life:) Internet" + carrier_id = "1950" + mcc="257" + mnc="04" + apn="internet.life.com.by" + authtype="1" + type="default,supl" + /> + + <apn carrier="life:) MMS" + carrier_id = "1950" + mcc="257" + mnc="04" + apn="mms.life.com.by" + authtype="1" + mmsc="http://mms.life.com.by/mmsc/" + mmsproxy="10.10.10.20" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange_Internet_GPRS" + carrier_id = "904" + mcc="259" + mnc="01" + apn="wap.orange.md" + type="default,supl" + /> + + <apn carrier="Orange_MMS_GPRS" + carrier_id = "904" + mcc="259" + mnc="01" + apn="mms.orange.md" + mmsc="http://mms/mms" + mmsproxy="192.168.127.125" + mmsport="3128" + type="mms" + /> + + <apn carrier="Moldcell Internet" + carrier_id = "905" + mcc="259" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Moldcell MMS" + carrier_id = "905" + mcc="259" + mnc="02" + apn="mms" + mmsc="http://mms.moldcell.md/cmmsc/post" + mmsproxy="10.0.10.10" + mmsport="9401" + type="mms" + /> + + <apn carrier="Unite Internet PrePay" + carrier_id = "2153" + mcc="259" + mnc="05" + apn="internet3g.unite.md" + type="default,supl" + /> + + <apn carrier="Unite Internet PostPay" + carrier_id = "2153" + mcc="259" + mnc="05" + apn="internet.unite.md" + type="default,supl" + /> + + <apn carrier="Unite MMS" + carrier_id = "2153" + mcc="259" + mnc="05" + apn="mms.unite.md" + mmsc="http://10.32.15.68:38090/was" + mmsproxy="10.32.15.164" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange MMS" + apn="mms.orange.md" + mmsc="http://mms/mms" + mmsproxy="192.168.127.125" + mmsport="3128" + carrier_id = "904" + mcc="259" + mnc="01" + type="mms" + /> + + <apn carrier="Plus Internet" + carrier_id = "1658" + mcc="260" + mnc="01" + apn="plus" + type="default,supl" + /> + + <apn carrier="Plus MMS" + carrier_id = "1658" + mcc="260" + mnc="01" + apn="mms" + mmsc="http://mms.plusgsm.pl:8002" + mmsproxy="212.2.96.16" + mmsport="8080" + type="mms" + /> + + <apn carrier="T-mobile.pl" + carrier_id = "2367" + mcc="260" + mnc="02" + apn="" + type="ia" + /> + + <apn carrier="T-mobile.pl" + carrier_id = "2367" + mcc="260" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="T-mobile.pl" + carrier_id = "2367" + mcc="260" + mnc="02" + apn="mms" + mmsc="http://mms/servlets/mms" + mmsproxy="213.158.194.226" + mmsport="8080" + type="mms" + /> + + <apn carrier="heyahinternet" + carrier_id = "2367" + mcc="260" + mnc="02" + apn="heyah.pl" + type="default,supl" + /> + + <apn carrier="heyahmms" + carrier_id = "2367" + mcc="260" + mnc="02" + apn="heyahmms" + mmsc="http://mms.heyah.pl/servlets/mms" + mmsproxy="213.158.194.226" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "1659" + mcc="260" + mnc="03" + apn="Internet" + user="internet" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "1659" + mcc="260" + mnc="03" + apn="mms" + user="mms" + password="mms" + mmsc="http://mms.orange.pl" + mmsproxy="192.168.6.104" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Play Internet" + carrier_id = "1662" + mcc="260" + mnc="06" + apn="internet" + type="default,supl" + /> + + <apn carrier="Play MMS" + carrier_id = "1662" + mcc="260" + mnc="06" + apn="mms" + mmsc="http://mmsc.play.pl/mms/wapenc" + type="mms" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="260" + mnc="33" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Rebtel" + carrier_id = "2229" + mcc="260" + mnc="44" + apn="rebtel" + mmsc="http://mmsc.rebtel.com" + mmsproxy="185.114.248.80" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Telekom Internet" + carrier_id = "2395" + mcc="262" + mnc="01" + apn="internet.telekom" + user="telekom" + password="telekom" + authtype="1" + type="default,supl,ia" + protocol="IPV4V6" + /> + + <apn carrier="Telekom Internet" + carrier_id = "2395" + mcc="262" + mnc="01" + apn="internet.telekom" + user="telekom" + password="telekom" + mmsc="http://mms.t-mobile.de/servlets/mms" + mmsproxy="109.237.176.193" + mmsport="8008" + bearer_bitmask="1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17" + authtype="1" + type="mms" + protocol="IPV4V6" + /> + + <apn carrier="Telekom Internet" + carrier_id = "2395" + mcc="262" + mnc="01" + apn="hos" + user="telekom" + password="telekom" + mmsc="http://mms.t-mobile.de/servlets/mms" + mmsproxy="109.237.176.193" + mmsport="8008" + bearer_bitmask="18" + authtype="1" + type="mms" + protocol="IPV4V6" + user_visible="false" + /> + + <apn carrier="Telekom Internet" + carrier_id = "2310" + mcc="262" + mnc="01" + apn="internet.telekom" + user="telekom" + password="telekom" + authtype="1" + mmsproxy="172.28.23.131" + mmsc="http://mms.t-mobile.de/servlets/mms" + mmsport="8008" + mvno_match_data="debitel" + mvno_type="spn" + protocol="IP" + /> + + <apn carrier="Vodafone DE" + carrier_id = "2397" + mcc="262" + mnc="02" + apn="" + type="ia" + protocol="IPV4V6" + /> + + <apn carrier="Vodafone DE-MMS" + carrier_id = "2397" + mcc="262" + mnc="02" + apn="event.vodafone.de" + mmsc="http://139.7.24.1/servlets/mms" + mmsproxy="139.7.29.17" + mmsport="80" + type="mms" + /> + + <apn carrier="Vodafone DE" + carrier_id = "2397" + mcc="262" + mnc="02" + apn="web.vodafone.de" + type="default,supl" + /> + + <apn carrier="Vodafone DE-IMS" + carrier_id = "2397" + mcc="262" + mnc="02" + apn="ims" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="E-Plus Internet" + carrier_id = "1453" + mcc="262" + mnc="03" + apn="internet.eplus.de" + user="eplus" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="E-Plus MMS" + carrier_id = "1453" + mcc="262" + mnc="03" + apn="mms.eplus.de" + user="mms" + password="eplus" + mmsc="http://mms/eplus/" + mmsproxy="212.23.97.153" + mmsport="5080" + authtype="1" + type="mms" + /> + + <apn carrier="MVNO DE" + carrier_id = "2461" + mcc="262" + mnc="03" + apn="internet.mvno.mobi" + user="mvno" + password="mvno" + authtype="1" + type="default,supl" + mvno_match_data="26203483" + mvno_type="imsi" + /> + + <apn carrier="o2 Internet" + mcc="262" + mnc="07" + apn="internet" + mmsc="http://10.81.0.7:8002" + mmsproxy="82.113.100.5" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="2620739" + mvno_type="imsi" + /> + + <apn carrier="O2 DE IMS" + carrier_id = "1454" + mcc="262" + mnc="07" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="o2 Internet Prepaid" + mcc="262" + mnc="07" + apn="pinternet.interkom.de" + mmsc="http://10.81.0.7:8002" + mmsproxy="82.113.100.6" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="2620749" + mvno_type="imsi" + /> + + <apn carrier="Fonic Prepaid" + carrier_id = "2328" + mcc="262" + mnc="07" + apn="pinternet.interkom.de" + mmsc="http://10.81.0.7:8002" + mmsproxy="82.113.100.6" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="26207515" + mvno_type="imsi" + /> + + <apn carrier="Lidl Mobile" + carrier_id = "2329" + mcc="262" + mnc="07" + apn="pinternet.interkom.de" + mmsc="http://10.81.0.7:8002" + mmsproxy="82.113.100.6" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="26207520" + mvno_type="imsi" + /> + + <apn carrier="Tchibo Internet" + carrier_id = "2330" + mcc="262" + mnc="07" + apn="webmobil1" + mmsc="http://10.81.0.7:8002" + mmsproxy="82.113.100.8" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="26207500" + mvno_type="imsi" + /> + + <apn carrier="O2 DE IMS" + carrier_id = "1454" + mcc="262" + mnc="08" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="MVNO DE" + carrier_id = "2461" + mcc="262" + mnc="20" + apn="internet.mvno.mobi" + user="mvno" + password="mvno" + authtype="1" + type="default,supl" + mvno_match_data="26220" + mvno_type="imsi" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="262" + mnc="42" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Vodafone Net2" + mcc="268" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="Vodafone Net2" + mcc="268" + mnc="01" + apn="net2.vodafone.pt" + user="vodafone" + password="vodafone" + authtype="1" + mmsc="http://mms.vodafone.pt/servlets/mms" + mmsproxy="iproxy.vodafone.pt" + mmsport="80" + type="default,supl,mms" + /> + + <apn carrier="vodafone P dun" + mcc="268" + mnc="01" + apn="internet.vodafone.pt" + authtype="0" + type="dun" + /> + + <apn carrier="PortalOptimus" + carrier_id = "1668" + mcc="268" + mnc="03" + apn="" + type="ia" + /> + + <apn carrier="PortalOptimus" + carrier_id = "1668" + mcc="268" + mnc="03" + apn="umts" + mmsc="http://mmsc:10021/mmsc" + mmsproxy="62.169.66.5" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="Optimus HotSpot" + carrier_id = "1668" + mcc="268" + mnc="03" + apn="modem" + type="dun" + /> + + <apn carrier="tmn internet" + carrier_id = "1670" + mcc="268" + mnc="06" + apn="" + type="ia" + /> + + <apn carrier="tmn internet" + carrier_id = "1670" + mcc="268" + mnc="06" + apn="internet" + type="default,supl" + /> + + <apn carrier="mms tmn" + carrier_id = "1670" + mcc="268" + mnc="06" + apn="mmsc.tmn.pt" + user="tmn" + password="tmnnet" + authtype="1" + mmsc="http://mmsc/" + mmsproxy="10.111.2.16" + mmsport="8080" + type="mms" + /> + + <apn carrier="LUXGSM MMS" + carrier_id = "895" + mcc="270" + mnc="01" + apn="mms.pt.lu" + user="mms" + password="mms" + mmsc="http://mmsc.pt.lu" + mmsproxy="194.154.192.88" + mmsport="8080" + type="mms" + /> + + <apn carrier="LUXGSM WAP" + carrier_id = "895" + mcc="270" + mnc="01" + apn="wap.pt.lu" + user="wap" + password="wap" + proxy="194.154.192.98" + port="8080" + type="default,supl" + /> + + <apn carrier="MTXC" + mcc="270" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Tango WAP" + carrier_id = "896" + mcc="270" + mnc="77" + apn="internet" + user="tango" + password="tango" + proxy="130.244.196.90" + port="8080" + type="default,supl" + /> + + <apn carrier="Tango MMS" + carrier_id = "896" + mcc="270" + mnc="77" + apn="mms" + user="tango" + password="tango" + mmsc="http://mms.tango.lu" + mmsproxy="212.66.75.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="270" + mnc="77" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="BB00" + mvno_type="gid" + /> + + <apn carrier="netgprs.com" + carrier_id = "2271" + mcc="270" + mnc="77" + apn="netgprs.com" + user="tsl" + password="tsl" + type="default,supl" + mvno_match_data="LU-Transatel" + mvno_type="spn" + /> + + <apn carrier="Orange" + carrier_id = "897" + mcc="270" + mnc="99" + apn="orange.lu" + mmsc="http://mms.orange.lu" + mmsproxy="212.88.139.44" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Vodafone IE" + carrier_id = "2387" + mcc="272" + mnc="01" + apn="live.vodafone.com" + type="default,supl" + /> + + <apn carrier="Vodafone IE-MMS" + carrier_id = "2387" + mcc="272" + mnc="01" + apn="mms.vodafone.net" + mmsc="http://www.vodafone.ie/mms" + mmsproxy="10.24.59.200" + mmsport="80" + type="mms" + /> + + <apn carrier="Vodafone MISP" + carrier_id = "2387" + mcc="272" + mnc="01" + apn="hs.vodafone.ie" + authtype="0" + user="vodafone" + password="vodafone" + type="dun" + /> + + <apn carrier="3" + carrier_id = "792" + mcc="272" + mnc="02" + apn="internet" + mmsc="http://mms.three.ie" + mmsproxy="62.40.32.40" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="O2.ie Mobile Hotspot" + carrier_id = "792" + mcc="272" + mnc="02" + apn="Open.internet" + authtype="0" + type="dun" + /> + + <apn carrier="Meteor Data" + carrier_id = "793" + mcc="272" + mnc="03" + apn="data.mymeteor.ie" + user="my" + password="wap" + authtype="1" + type="default,supl" + /> + + <apn carrier="Meteor MMS" + carrier_id = "793" + mcc="272" + mnc="03" + apn="mms.mymeteor.ie" + user="my" + password="wap" + authtype="1" + mmsc="http://mms.mymeteor.ie" + mmsproxy="10.85.85.85" + mmsport="8799" + type="mms" + /> + + <apn carrier="3" + carrier_id = "1903" + mcc="272" + mnc="05" + apn="3ireland.ie" + mmsc="http://mms.um.3ireland.ie:10021/mmsc" + mmsproxy="mms.3ireland.ie" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="Tesco" + carrier_id = "2154" + mcc="272" + mnc="11" + apn="tescomobile.liffeytelecom.com" + mmsc="http://mmc1/servlets/mms" + mmsproxy="10.1.11.19" + mmsport="8080" + type="default,supl,mms" + mvno_match_data="0A" + mvno_type="gid" + /> + + <apn carrier="Siminn Internet" + carrier_id = "1565" + mcc="274" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="Siminn MMS" + carrier_id = "1565" + mcc="274" + mnc="01" + apn="mms.simi.is" + mmsc="http://mms.simi.is/servlets/mms" + mmsproxy="213.167.138.200" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone Internet" + carrier_id = "1566" + mcc="274" + mnc="02" + apn="gprs.is" + type="default,supl" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "1566" + mcc="274" + mnc="02" + apn="mms.gprs.is" + mmsc="http://mmsc.vodafone.is" + mmsproxy="10.22.0.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone Internet" + carrier_id = "1567" + mcc="274" + mnc="03" + apn="gprs.is" + authtype="0" + type="default,supl,agps,fota,dun" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "1567" + mcc="274" + mnc="03" + apn="mms.gprs.is" + authtype="0" + mmsc="http://mmsc.vodafone.is" + mmsproxy="10.22.0.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="MMS Nova" + carrier_id = "2155" + mcc="274" + mnc="11" + apn="mms.nova.is" + mmsc="http://mmsc.nova.is" + mmsproxy="10.10.2.60" + mmsport="8080" + type="mms" + /> + + <apn carrier="Net Nova" + carrier_id = "2155" + mcc="274" + mnc="11" + apn="net.nova.is" + proxy="10.10.2.60" + port="8080" + type="default,supl" + /> + + <apn carrier="Vodafone MT" + carrier_id = "2368" + mcc="278" + mnc="01" + apn="internet" + user="internet" + password="internet" + type="default,supl" + /> + + <apn carrier="Vodafone MT-MMS" + carrier_id = "2368" + mcc="278" + mnc="01" + apn="mms.vodafone.com.mt" + mmsc="http://mms.vodafone.com.mt/servlets/mms" + mmsproxy="10.12.0.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="CYTA" + carrier_id = "1447" + mcc="280" + mnc="01" + apn="cytamobile" + mmsc="http://mmsc.cyta.com.cy" + mmsproxy="212.31.96.161" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="MTN MMS" + carrier_id = "1448" + mcc="280" + mnc="10" + apn="mms" + user="mms" + password="mms" + mmsc="http://mms.mtn.com.cy/mmsc" + mmsproxy="172.24.97.1" + mmsport="3130" + type="mms" + /> + + <apn carrier="MTN Internet" + carrier_id = "1448" + mcc="280" + mnc="10" + apn="internet" + type="default,supl" + /> + + <apn carrier="PrimeTel" + carrier_id = "2156" + mcc="280" + mnc="20" + apn="ip.primetel" + mmsc="http://mms.primetel" + type="default,supl,mms" + /> + + <apn carrier="MTel" + carrier_id = "1370" + mcc="284" + mnc="01" + apn="inet-gprs.mtel.bg" + type="default,supl" + /> + + <apn carrier="MTel MMS" + carrier_id = "1370" + mcc="284" + mnc="01" + apn="mms-gprs.mtel.bg" + user="mtel" + password="mtel" + authtype="1" + mmsc="http://mmsc/" + mmsproxy="10.150.0.33" + mmsport="8080" + type="mms" + /> + + <apn carrier="VIVACOM Internet" + carrier_id = "1999" + mcc="284" + mnc="03" + apn="internet.vivacom.bg" + user="vivacom" + password="vivacom" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vivacom MMS" + carrier_id = "1999" + mcc="284" + mnc="03" + apn="mms.vivacom.bg" + user="mms" + password="mms" + authtype="1" + mmsc="http://mmsc.vivacom.bg" + mmsproxy="192.168.123.123" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telenor Internet" + carrier_id = "1371" + mcc="284" + mnc="05" + apn="telenorbg" + authtype="0" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1371" + mcc="284" + mnc="05" + apn="mms" + user="mms" + authtype="1" + mmsc="http://mmsc" + mmsproxy="192.168.87.11" + mmsport="8004" + type="mms" + /> + + <apn carrier="bulsatcom" + carrier_id = "2230" + mcc="284" + mnc="11" + apn="bulsat.com" + type="default,supl" + /> + + <apn carrier="MAX TELECOM" + carrier_id = "2231" + mcc="284" + mnc="13" + apn="apn.maxtelecom.bg" + type="default,supl" + /> + + <apn carrier="TURKCELL INTERNET" + carrier_id = "1735" + mcc="286" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="TURKCELL MMS" + carrier_id = "1735" + mcc="286" + mnc="01" + apn="mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.turkcell.com.tr/servlets/mms" + mmsproxy="212.252.169.217" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone internet" + carrier_id = "1736" + mcc="286" + mnc="02" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "1736" + mcc="286" + mnc="02" + apn="mms" + user="vodafone" + password="vodafone" + authtype="1" + mmsc="http://217.31.233.18:6001/MM1Servlet" + mmsproxy="217.31.233.18" + mmsport="9401" + type="mms" + /> + + <apn carrier="AVEA INTERNET" + carrier_id = "1737" + mcc="286" + mnc="03" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="AVEA MMS" + carrier_id = "1737" + mcc="286" + mnc="03" + apn="mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.avea.com.tr/servlets/mms" + mmsproxy="213.161.151.201" + mmsport="8080" + type="mms" + /> + + <apn carrier="Tele Internet" + carrier_id = "735" + mcc="290" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="Tele MMS" + carrier_id = "735" + mcc="290" + mnc="01" + apn="mms" + mmsc="http://mms.tele.gl/mms/wapenc" + mmsproxy="10.112.222.37" + mmsport="8080" + type="mms" + /> + + <apn carrier="Si.mobil GPRS" + carrier_id = "1709" + mcc="293" + mnc="40" + apn="internet.simobil.si" + user="simobil" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Si.mobil MMS" + carrier_id = "1709" + mcc="293" + mnc="40" + apn="mms.simobil.si" + user="simobil" + password="internet" + authtype="1" + mmsc="http://mmc/" + mmsproxy="80.95.224.46" + mmsport="9201" + type="mms" + /> + + <apn carrier="Mobilni Internet" + carrier_id = "1710" + mcc="293" + mnc="41" + apn="internet" + user="mobitel" + password="internet" + authtype="1" + mmsc="http://mms.mobitel.si/servlets/mms" + mmsproxy="213.229.249.40" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="T2" + carrier_id = "1711" + mcc="293" + mnc="64" + apn="internet.t-2.net" + mmsc="http://www.mms.t-2.net:8002" + mmsproxy="172.20.18.137" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Tusmobil Internet" + carrier_id = "1712" + mcc="293" + mnc="70" + apn="internet.tusmobil.si" + user="tusmobil" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Tusmobil MMS" + carrier_id = "1712" + mcc="293" + mnc="70" + apn="mms.tusmobil.si" + user="tusmobil" + password="mms" + authtype="1" + mmsc="http://mms.tusmobil.si:8002" + mmsproxy="91.185.221.85" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telemach Internet" + carrier_id = "2327" + mcc="293" + mnc="70" + apn="telemach.net" + mmsc="http://mms.telemach.net:8002" + mmsproxy="91.185.221.85" + mmsport="8080" + mvno_type="imsi" + mvno_match_data="29370029xxxxxxx" + type="default,supl,mms" + /> + + <apn carrier="T-Mobile MK Internet" + carrier_id = "2396" + mcc="294" + mnc="01" + apn="" + type="ia" + /> + + <apn carrier="T-Mobile MK Internet" + carrier_id = "2396" + mcc="294" + mnc="01" + apn="internet" + user="internet" + password="t-mobile" + type="default,supl" + /> + + <apn carrier="T-Mobile MK MMS" + carrier_id = "2396" + mcc="294" + mnc="01" + apn="mms" + user="mms" + password="mms" + mmsc="http://mms.t-mobile.com.mk" + mmsproxy="62.162.155.227" + mmsport="8080" + type="mms" + /> + + <apn carrier="Cosmofon" + carrier_id = "1608" + mcc="294" + mnc="02" + apn="Internet" + user="Internet" + password="Internet" + proxy="http://wap.planet.mk" + port="8080" + type="default,supl" + /> + + <apn carrier="Cosmofon MMS" + carrier_id = "1608" + mcc="294" + mnc="02" + apn="mms" + mmsc="http://195.167.65.220:8002" + mmsproxy="10.10.10.20" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1609" + mcc="294" + mnc="03" + apn="vipoperator" + user="vipoperator" + password="vipoperator" + proxy="78.40.0.1" + port="8080" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1609" + mcc="294" + mnc="03" + apn="vipoperator.mms" + user="vipoperator" + password="vipoperator" + mmsc="http://mmsc.vipoperator.com.mk" + mmsproxy="78.40.0.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="EMnify" + carrier_id = "2326" + mcc="295" + mnc="05" + apn="em" + mvno_match_data="2950509" + mvno_type="imsi" + type="default,supl" + /> + + <apn carrier="EMnify" + carrier_id = "2233" + mcc="295" + mnc="09" + apn="em" + type="default,supl" + /> + + <apn carrier="BICS" + carrier_id = "2232" + mcc="295" + mnc="09" + apn="bicsapn" + mvno_match_data="BICS" + mvno_type="spn" + type="default" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "2088" + mcc="297" + mnc="02" + apn="mms" + user="38267" + password="38267" + mmsc="http://192.168.180.100/servlets/mms" + mmsproxy="10.0.5.19" + mmsport="8080" + type="mms" + mvno_match_data="Telekom.me" + mvno_type="spn" + /> + + <apn carrier="T-Mobile Internet" + carrier_id = "2088" + mcc="297" + mnc="02" + apn="tmcg-wnw" + user="38267" + password="38267" + proxy="10.0.5.19" + port="8080" + type="default,supl" + mvno_match_data="Telekom.me" + mvno_type="spn" + /> + + <apn carrier="TELUS" + carrier_id = "1404" + mcc="302" + mnc="220" + apn="sp.telus.com" + type="default,mms,supl" + mmsc="http://aliasredirect.net/proxy/mmsc" + mmsproxy="mmscproxy.mobility.ca" + mmsport="8799" + mvno_match_data="5455" + mvno_type="gid" + /> + + <apn carrier="TELUS Tether" + carrier_id = "1404" + mcc="302" + mnc="220" + apn="isp.telus.com" + server="*" + type="dun" + protocol="IPV4" + mvno_match_data="5455" + mvno_type="gid" + /> + + <apn carrier="Koodo" + carrier_id = "2020" + mcc="302" + mnc="220" + apn="sp.koodo.com" + type="default,mms,supl" + mmsc="http://aliasredirect.net/proxy/koodo/mmsc" + mmsproxy="mmscproxy.mobility.ca" + mmsport="8799" + mvno_match_data="4B4F" + mvno_type="gid" + /> + + <apn carrier="Koodo Tether" + carrier_id = "2020" + mcc="302" + mnc="220" + apn="sp.koodo.com" + server="*" + type="dun" + protocol="IPV4" + mvno_match_data="4B4F" + mvno_type="gid" + /> + + <apn carrier="Mobile Internet" + carrier_id = "2053" + mcc="302" + mnc="220" + apn="sp.mb.com" + type="default,mms,supl" + mmsc="http://aliasredirect.net/proxy/mb/mmsc" + mmsproxy="mmscproxy.mobility.ca" + mmsport="8799" + mvno_match_data="5043" + mvno_type="gid" + /> + + <apn carrier="Tethered Mobile Internet" + carrier_id = "2053" + mcc="302" + mnc="220" + apn="isp.mb.com" + type="dun" + protocol="IPV4" + mvno_type="gid" + mvno_match_data="5043" + /> + + <apn carrier="Mobile Internet" + carrier_id = "2089" + mcc="302" + mnc="220" + apn="sp.mb.com" + type="default,mms,agps,supl,fota,hipri" + mmsc="http://aliasredirect.net/proxy/mb/mmsc" + mmsproxy="mmscproxy.mobility.ca" + mmsport="8799" + mvno_type="gid" + mvno_match_data="4D4F" + /> + + <apn carrier="Tethered Mobile Internet" + carrier_id = "2089" + mcc="302" + mnc="220" + apn="isp.mb.com" + type="dun" + protocol="IPV4" + mvno_type="gid" + mvno_match_data="4D4F" + /> + + <apn carrier="TELUS ISP" + carrier_id = "1404" + mcc="302" + mnc="221" + apn="isp.telus.com" + server="*" + type="dun" + protocol="IPV4" + mvno_match_data="5455" + mvno_type="gid" + /> + + <apn carrier="Koodo" + carrier_id = "2020" + mcc="302" + mnc="221" + apn="sp.koodo.com" + server="*" + type="dun" + protocol="IPV4" + mvno_match_data="4B4F" + mvno_type="gid" + /> + + <apn carrier="Tethered PC Mobile" + carrier_id = "2053" + mcc="302" + mnc="221" + apn="isp.mb.com" + type="dun" + protocol="IPV4" + mvno_type="gid" + mvno_match_data="5043" + /> + + <apn carrier="MOWAP" + carrier_id = "2055" + mcc="302" + mnc="320" + apn="wap.davewireless.com" + proxy="10.100.3.4" + port="8080" + type="default,supl" + /> + + <apn carrier="MOMMS" + carrier_id = "2055" + mcc="302" + mnc="320" + apn="mms.davewireless.com" + mmsc="http://mms.mobilicity.net" + mmsproxy="10.100.3.4" + mmsport="8080" + type="mms" + /> + + <apn carrier="MMS" + carrier_id = "2252" + mcc="302" + mnc="270" + apn="mms.mobi.eastlink.ca" + mmsc="http://mmss.mobi.eastlink.ca" + mmsproxy="10.232.12.49" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "2252" + mcc="302" + mnc="270" + apn="wisp.mobi.eastlink.ca" + type="default,supl" + /> + + <apn carrier="Rogers IMS" + carrier_id = "1962" + mcc="302" + mnc="370" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Fido Tethering" + carrier_id = "1962" + mcc="302" + mnc="370" + apn="ltedata.apn" + type="dun" + mvno_match_data="DD" + mvno_type="gid" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Fido Internet" + carrier_id = "1962" + mcc="302" + mnc="370" + apn="ltemobile.apn" + type="default,mms,agps,supl,fota,hipri" + mmsproxy="mmsproxy.fido.ca" + mmsc="http://mms.fido.ca" + mmsport="80" + mvno_match_data="DD" + mvno_type="gid" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Fido Internet" + carrier_id = "1962" + mcc="302" + mnc="370" + apn="IMS" + type="ims" + mvno_match_data="DD" + mvno_type="gid" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="MTS" + carrier_id = "578" + mcc="302" + mnc="370" + apn="sp.mts" + type="default,mms,supl" + mmsc="http://mmsc2.mts.net/" + mmsproxy="wapgw1.mts.net" + mmsport="9201" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="2C" + mvno_type="gid" + /> + + <apn carrier="MTS Tethering S" + carrier_id = "578" + mcc="302" + mnc="370" + apn="internet.mts" + type="dun" + protocol="IPV4V6" + roaming_protocol="IP" + mvno_type="gid" + mvno_match_data="2C" + /> + + <apn carrier="Internet" + carrier_id = "1895" + mcc="302" + mnc="490" + apn="internet.windmobile.ca" + type="default,supl" + protocol="IPV4V6" + /> + + <apn carrier="MMS" + carrier_id = "1895" + mcc="302" + mnc="490" + apn="mms.windmobile.ca" + mmsc="http://mms.windmobile.ca" + mmsproxy="74.115.197.70" + mmsport="8080" + type="mms" + /> + + <apn carrier="Media" + carrier_id = "2008" + mcc="302" + mnc="500" + apn="media.ng" + mmsc="http://media.videotron.com" + type="default,supl,mms" + /> + + <apn carrier="Media" + carrier_id = "2008" + mcc="302" + mnc="510" + apn="media.ng" + mmsc="http://media.videotron.com" + type="default,supl,mms" + /> + + <apn carrier="Media" + carrier_id = "2008" + mcc="302" + mnc="520" + apn="media.ng" + mmsc="http://media.videotron.com" + type="default,supl,mms" + /> + + <apn carrier="Bell Mobility" + carrier_id = "576" + mcc="302" + mnc="610" + apn="pda.bell.ca" + type="default,mms,supl" + mmsc="http://mms.bell.ca/mms/wapenc" + /> + + <apn carrier="Bell Mobility IMS" + carrier_id = "576" + mcc="302" + mnc="610" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="MTS" + mcc="302" + mnc="660" + apn="sp.mts" + type="default,mms,supl" + mmsc="http://mmsc2.mts.net/" + mmsproxy="wapgw1.mts.net" + mmsport="9201" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="spn" + mvno_match_data="MTS" + /> + + <apn carrier="MTS Tethering" + mcc="302" + mnc="660" + apn="internet.mts" + type="dun" + protocol="IPV4V6" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="MTS" + /> + + <apn carrier="Rogers LTE" + carrier_id = "1403" + mcc="302" + mnc="720" + apn="ltemobile.apn" + type="default,mms,supl" + mmsproxy="mmsproxy.rogers.com" + mmsc="http://mms.gprs.rogers.com" + mmsport="80" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Rogers IMS" + carrier_id = "1403" + mcc="302" + mnc="720" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="chatr" + carrier_id = "2055" + mcc="302" + mnc="720" + apn="chatrweb.apn" + type="default,mms,supl" + mmsc="http://mms.chatrwireless.com" + mmsproxy="205.151.11.11" + mmsport="80" + proxy="205.151.11.11" + port="80" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="302720x94" + mvno_type="imsi" + /> + + <apn carrier="Chatr Tethering" + carrier_id = "2055" + mcc="302" + mnc="720" + apn="chatrisp.apn" + type="dun" + mvno_type="imsi" + mvno_match_data="302720x94" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Tbaytel Tethering" + carrier_id = "2090" + mcc="302" + mnc="720" + apn="ltedata.apn" + type="dun" + protocol="IPV4V6" + roaming_protocol="IP" + mvno_type="gid" + mvno_match_data="BA" + /> + + <apn carrier="Tbaytel Internet" + mnc="720" + carrier_id = "2090" + mcc="302" + apn="ltemobile.apn" + type="default,mms,agps,supl,fota,hipri" + protocol="IPV4V6" + roaming_protocol="IP" + mmsc="http://mms.gprs.rogers.com" + mmsproxy="mmsproxy.rogers.com" + mmsport="80" + mvno_type="gid" + mvno_match_data="BA" + /> + + <apn carrier="Cityfone Tethering" + carrier_id = "2057" + mcc="302" + mnc="720" + apn="ltedata.apn" + type="dun" + protocol="IPV4V6" + roaming_protocol="IP" + mvno_type="spn" + mvno_match_data="CITYFONE" + /> + + <apn carrier="Cityfone Internet" + mnc="720" + carrier_id = "2057" + mcc="302" + apn="ltemobile.apn" + type="default,mms,agps,supl,fota,hipri" + protocol="IPV4V6" + roaming_protocol="IP" + mmsc="http://mms.gprs.rogers.com" + mmsproxy="mmsproxy.rogers.com" + mmsport="80" + mvno_type="spn" + mvno_match_data="CITYFONE" + /> + + <apn carrier="Rogers Tethering" + mcc="302" + mnc="720" + apn="ltedata.apn" + type="dun" + mvno_match_data="ROGERS" + mvno_type="spn" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="Rogers Internet" + mcc="302" + mnc="720" + apn="ltemobile.apn" + type="default,mms,agps,supl,fota,hipri" + mmsproxy="mmsproxy.rogers.com" + mmsc="http://mms.gprs.rogers.com" + mmsport="80" + mvno_match_data="ROGERS" + mvno_type="spn" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="SaskTel" + carrier_id = "580" + mcc="302" + mnc="780" + apn="pda.stm.sk.ca" + type="default,mms,supl" + mmsc="http://mms.sasktel.com/" + mmsproxy="mig.sasktel.com" + mmsport="80" + /> + + <apn carrier="Verizon CDMA HRPD" + mcc="310" + mnc="000" + mmsc="http://mms.vzwreseller.com/servlets/mms" + type="default,mms,hipri,dun,supl" + mvno_type="spn" + mvno_match_data="Tracfone" + authtype="3" + /> + + <apn carrier="Bluewire" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="bluewire" + mmsc="http://mms.blueunlimited.com" + mmsproxy="" + mmsport="8514" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Bluewire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="bluewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluewire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="bluewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Bluewire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="bluewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluewire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="bluewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Bluewire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.blueunlimited.com" + mmsproxy="" + mmsport="8514" + mvno_type="spn" + mvno_match_data="bluewire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluewire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.blueunlimited.com" + mmsproxy="" + mmsport="8514" + mvno_type="spn" + mvno_match_data="bluewire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="flatwire" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="flatwire" + mmsc="http://mmsc.cleartalk.csky.us/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Flatwire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="flatwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Flatwire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="flatwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Flatwire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="flatwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Flatwire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="flatwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Flatwire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mmsc.cleartalk.csky.us/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="flatwire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Flatwire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mmsc.cleartalk.csky.us/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="flatwire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="mobipcs" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="mobipcs" + mmsc="http://mms.mobipcs.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Mobipcs IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mobipcs" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobipcs IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mobipcs" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mobipcs FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mobipcs" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobipcs FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mobipcs" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mobipcs" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mobipcs.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="mobipcs" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobipcs" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mobipcs.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="mobipcs" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="mobilenation" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="mobilenation" + mmsc="http://mms.mymn3g.net" + mmsproxy="mms.mymn3g.net" + mmsport="8081" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Mobilenation IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mobilenation" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobilenation IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mobilenation" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mobilenation FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mobilenation" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobilenation FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mobilenation" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mobilenation" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mymn3g.net" + mmsproxy="mms.mymn3g.net" + mmsport="8081" + mvno_type="spn" + mvno_match_data="mobilenation" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mobilenation" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mymn3g.net" + mmsproxy="mms.mymn3g.net" + mmsport="8081" + mvno_type="spn" + mvno_match_data="mobilenation" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="mohave" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="mohave" + mmsc="http://mms.mohavewireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Mohave IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mohave" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mohave IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="mohave" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mohave FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mohave" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mohave FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="mohave" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mohave" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mohavewireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="mohave" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mohave" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.mohavewireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="mohave" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="peopleswire" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="peopleswire" + mmsc="http://172.16.16.130/mms/" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Peopleswire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="Peopleswire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Peopleswire IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="Peopleswire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="peopleswire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="peopleswire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="peopleswire FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="peopleswire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Peopleswire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://172.16.16.130/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="Peopleswire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Peopleswire" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://172.16.16.130/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="Peopleswire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="revol" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="revol" + mmsc="http://mms.revol.us/revol/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Revol IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="revol" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Revol IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="revol" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Revol FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="revol" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Revol FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="revol" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Revol" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.revol.us/revol/mms.php" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="revol" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Revol" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.revol.us/revol/mms.php" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="revol" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Commnet" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="commnet" + mmsc="http://mmsc.cccomm.csky.us" + mmsproxy="" + mmsport="6672" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="distribution" + mcc="310" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="distribution" + mmsc="http://mms.dst.com/mms/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Distribution IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="distribution" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Distribution IMS" + mcc="310" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="distribution" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Distribution FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="distribution" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Distribution FOTA" + mcc="310" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="distribution" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Distribution" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.dst.com/mms/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="distribution" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Distribution" + mcc="310" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.dst.com/mms/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="distribution" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Union Wireless Data" + carrier_id = "1781" + mcc="310" + mnc="020" + apn="union.wap.com" + proxy="166.230.4.83" + port="8799" + type="default,hipri,dun,supl" + /> + + <apn carrier="Union Wireless MMS" + carrier_id = "1781" + mcc="310" + mnc="020" + apn="union.mms.com" + mmsc="http://mmsc/01" + mmsproxy="166.230.4.83" + mmsport="8799" + type="mms" + /> + + <!-- Need two APNs for CDMA technologies: a default that is used normally --> + <!-- and a second APN to be used when DUN is required. Even though the --> + <!-- parameters appear the same, the profileID sent to the radio when requesting --> + <!-- a DUN connection will be different --> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Verizon" + mcc="310" + mnc="004" + apn="internet" + authtype="3" + type="default,mms,supl,fota,cbs" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + /> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Verizon" + mcc="310" + mnc="004" + apn="internet" + authtype="3" + type="default,mms,supl,fota,cbs,dun" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + profile_id="1" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Verizon Internet" + mcc="310" + mnc="004" + apn="VZWINTERNET" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Verizon FOTA" + mcc="310" + mnc="004" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Verizon IMS" + mcc="310" + mnc="004" + apn="VZWIMS" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 13, 14 --> + <apn carrier="Verizon CBS" + mcc="310" + mnc="004" + apn="VZWAPP" + type="cbs,mms" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13|14" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier=" ALU Test-SIM Internet" + carrier_id = "2253" + mcc="310" + mnc="028" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier=" ALU Test-SIM FOTA" + carrier_id = "2253" + mcc="310" + mnc="028" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier=" ALU Test-SIM IMS" + carrier_id = "2253" + mcc="310" + mnc="028" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier=" ALU Test-SIM CBS" + carrier_id = "2253" + mcc="310" + mnc="028" + apn="VZWAPP" + mmsc="http://mms.vtext.com/servlets/mms" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="myBlue Pix" + carrier_id = "1187" + mcc="310" + mnc="030" + apn="mmswap.centennialwireless.com" + mmsc="http://mms.myblue.com/servlets/mms" + mmsproxy="63.99.231.135" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1187" + mcc="310" + mnc="030" + apn="private.centennialwireless.com" + user="privuser" + password="priv" + type="default,supl" + /> + + <apn carrier="itewire" + mcc="310" + mnc="032" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="itewire" + mmsc="" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Itewire IMS" + mcc="310" + mnc="032" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="itewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Itewire IMS" + mcc="310" + mnc="032" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="itewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Itewire FOTA" + mcc="310" + mnc="032" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="itewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Itewire FOTA" + mcc="310" + mnc="032" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="itewire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Itewire" + mcc="310" + mnc="032" + apn="VZWINTERNET" + mmsc="" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="itewire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Itewire" + mcc="310" + mnc="032" + apn="VZWINTERNET" + mmsc="" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="itewire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="etex" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="etex" + mmsc="http://mmsi.etex.mobi" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Etex IMS" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="etex" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Etex IMS" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="etex" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Etex FOTA" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="etex" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Etex FOTA" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="etex" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Etex" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWINTERNET" + mmsc="http://mmsi.etex.mobi" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="etex" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Etex" + carrier_id = "2254" + mcc="310" + mnc="035" + apn="VZWINTERNET" + mmsc="http://mmsi.etex.mobi" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="etex" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="mta" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="CdmaNai" + mmsc="http://mmsc.mta.dataonair.net/" + mmsproxy="209.4.229.85" + mmsport="6672" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Mta IMS" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mta IMS" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mta FOTA" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mta FOTA" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Mta" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWINTERNET" + mmsc="http://mmsc.mta.dataonair.net/" + mmsproxy="209.4.229.85" + mmsport="6672" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Mta" + carrier_id = "1784" + mcc="310" + mnc="040" + apn="VZWINTERNET" + mmsc="http://mmsc.mta.dataonair.net/" + mmsproxy="209.4.229.85" + mmsport="6672" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="alaskacomm" + mcc="310" + mnc="050" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="alaskacomm" + mmsc="http://mmsc1.acsalaska.net/servlets/mms" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Alaskacomm IMS" + mcc="310" + mnc="050" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="alaskacomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alaskacomm IMS" + mcc="310" + mnc="050" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="alaskacomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Alaskacomm FOTA" + mcc="310" + mnc="050" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="alaskacomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alaskacomm FOTA" + mcc="310" + mnc="050" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="alaskacomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Alaskacomm" + mcc="310" + mnc="050" + apn="VZWINTERNET" + mmsc="http://mmsc1.acsalaska.net/servlets/mms" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="alaskacomm" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alaskacomm" + mcc="310" + mnc="050" + apn="VZWINTERNET" + mmsc="http://mmsc1.acsalaska.net/servlets/mms" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="alaskacomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="U.S.Cellular" + mcc="310" + mnc="066" + apn="internet" + user="*" + server="*" + password="*" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + mtu="1422" + /> + + <apn carrier="Corr Wap" + carrier_id = "1168" + mcc="310" + mnc="080" + apn="corrgprs" + server="http://w.iot1.com/corr/wml.php" + proxy="74.112.57.172" + port="9201" + type="default" + /> + + <apn carrier="CorrMMS" + carrier_id = "1168" + mcc="310" + mnc="080" + apn="corrmms" + mmsc="http://mms.iot1.com/corr/mms.php" + mmsproxy="66.255.55.23" + mmsport="80" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1779" + mcc="310" + mnc="090" + apn="isp" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="MMS" + carrier_id = "1779" + mcc="310" + mnc="090" + apn="mms" + mmsc="http://mms.edgemobile.net/mmsc" + mmsproxy="12.108.12.13" + mmsport="3128" + type="mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Edge MMS Prepay" + carrier_id = "1779" + mcc="310" + mnc="090" + apn="ppmms" + mmsc="http://mms.edgemobile.net/mmsc" + mmsproxy="12.108.12.13" + mmsport="3128" + type="mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="PLATMMS" + carrier_id = "1170" + mcc="310" + mnc="100" + apn="mms.plateau" + mmsc="http://mms" + mmsproxy="172.23.253.206" + mmsport="8080" + type="mms" + /> + + <apn carrier="PLATWEB" + carrier_id = "1170" + mcc="310" + mnc="100" + apn="isp.plateau" + type="default,supl" + /> + + <!-- Need two APNs for CDMA technologies: a default that is used normally --> + <!-- and a second APN to be used when DUN is required. Even though the --> + <!-- parameters appear the same, the profileID sent to the radio when requesting --> + <!-- a DUN connection will be different --> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Sprint" + carrier_id = "1788" + mcc="310" + mnc="120" + apn="sprint" + type="default,supl,mms,ims,cbs" + mmsc="http://mms.sprintpcs.com" + mmsproxy="68.28.31.7" + mmsport="80" + bearer_bitmask="4|5|6|7|8|12" + /> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Sprint" + carrier_id = "1788" + mcc="310" + mnc="120" + apn="sprint" + type="default,supl,mms,ims,cbs,dun" + mmsc="http://mms.sprintpcs.com" + mmsproxy="68.28.31.7" + mmsport="80" + bearer_bitmask="4|5|6|7|8|12" + profile_id="1" + /> + + <!-- this APN will be deleted and replaced by a new ia APN by the HFA provisioning process. + This is just a bootstrap APN to enable HFA --> + <apn carrier="OTA" + carrier_id = "1788" + mcc="310" + mnc="120" + apn="otasn" + type="fota,ia" + protocol="IPV4V6" + user="null" + password="null" + /> + + <!-- bearer 1, 2, 3, 9, 10, 11, 15, 16 --> + <apn carrier="SPCS Global" + carrier_id = "1788" + mcc="310" + mnc="120" + apn="cinet.spcs" + mmsc="http://mms.sprintpcs.com" + mmsproxy="68.28.31.7" + mmsport="80" + type="default,supl,mms,dun" + bearer_bitmask="1|2|3|9|10|11|15|16" + /> + + <apn carrier="Carolina West Internet" + carrier_id = "1789" + mcc="310" + mnc="130" + apn="home.cww.com" + type="default,supl,mms,ims,cbs" + mmsc="http://mms.cwwmms.com/cww/mms.php" + mmsport="80" + bearer_bitmask="4|5|6|7|8|12" + /> + + <apn carrier="Carolina West Tethering" + carrier_id = "1789" + mcc="310" + mnc="130" + apn="tethering.cww.com" + type="dun" + bearer_bitmask="4|5|6|7|8|12" + user_editable="false" + /> + + <apn carrier="internet" + carrier_id = "1964" + mcc="310" + mnc="150" + apn="ndo" + user="" + password="" + proxy="" + port="" + mmsc="http://mmsc.aiowireless.net" + mmsproxy="proxy.aiowireless.net" + mmsport="80" + type="default,mms,fota,hipri,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + + <apn carrier="T-Mobile US 160" + carrier_id = "1" + mcc="310" + mnc="160" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 160 DUN" + carrier_id = "1" + mcc="310" + mnc="160" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 160" + carrier_id = "1949" + mcc="310" + mnc="160" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 160" + carrier_id = "1949" + mcc="310" + mnc="160" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="IMS" + carrier_id = "1187" + mcc="310" + mnc="170" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + + <apn carrier="DataConnect" + carrier_id = "1187" + mcc="310" + mnc="170" + apn="isp.cingular" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Cingular MMS" + carrier_id = "1187" + mcc="310" + mnc="170" + apn="wap.cingular" + user="WAP@CINGULARGPRS.COM" + password="CINGULAR1" + mmsc="http://mmsc.cingular.com" + mmsproxy="66.209.11.32" + mmsport="8080" + type="mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="WCW-INTERNET" + carrier_id = "1792" + mcc="310" + mnc="180" + apn="internet.wcc.net" + user="13257630000" + password="mmsc" + type="default" + /> + + <apn carrier="WCW-MMS" + carrier_id = "1792" + mcc="310" + mnc="180" + apn="mms.wcc.net" + user="13257630000" + password="mmsc" + authtype="3" + mmsc="http://mms.wcc.net" + mmsproxy="209.55.70.246" + mmsport="80" + type="mms" + /> + + <apn carrier="T-Mobile US 200" + carrier_id = "1" + mcc="310" + mnc="200" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 200 DUN" + carrier_id = "1" + mcc="310" + mnc="200" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 200" + carrier_id = "1949" + mcc="310" + mnc="200" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 200" + carrier_id = "1949" + mcc="310" + mnc="200" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 210" + carrier_id = "1" + mcc="310" + mnc="210" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 210 DUN" + carrier_id = "1" + mcc="310" + mnc="210" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 210" + carrier_id = "1949" + mcc="310" + mnc="210" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 210" + carrier_id = "1949" + mcc="310" + mnc="210" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 220" + carrier_id = "1" + mcc="310" + mnc="220" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 220 DUN" + carrier_id = "1" + mcc="310" + mnc="220" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 220" + carrier_id = "1949" + mcc="310" + mnc="220" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 220" + carrier_id = "1949" + mcc="310" + mnc="220" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 230" + carrier_id = "1" + mcc="310" + mnc="230" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 230 DUN" + carrier_id = "1" + mcc="310" + mnc="230" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 230" + carrier_id = "1949" + mcc="310" + mnc="230" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 230" + carrier_id = "1949" + mcc="310" + mnc="230" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 240" + carrier_id = "1" + mcc="310" + mnc="240" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 240 DUN" + carrier_id = "1" + mcc="310" + mnc="240" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 240" + carrier_id = "1949" + mcc="310" + mnc="240" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 240" + carrier_id = "1949" + mcc="310" + mnc="240" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 250" + carrier_id = "1" + mcc="310" + mnc="250" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 250 DUN" + carrier_id = "1" + mcc="310" + mnc="250" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + mtu="1440" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 250" + carrier_id = "1949" + mcc="310" + mnc="250" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 250" + carrier_id = "1949" + mcc="310" + mnc="250" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile GPRS" + carrier_id = "1" + mcc="310" + mnc="260" + apn="fast.t-mobile.com" + type="default,supl,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "1" + mcc="310" + mnc="260" + apn="TMUS" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="mms" + protocol="IPV6" + roaming_protocol="IP" + bearer_bitmask="1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17" + /> + + <apn carrier="T-Mobile MMS" + carrier_id = "1" + mcc="310" + mnc="260" + apn="TMUS" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="mms" + protocol="IPV6" + roaming_protocol="IPV6" + bearer="18" + /> + + <apn carrier="T-Mobile IMS" + carrier_id = "1" + mcc="310" + mnc="260" + apn="ims" + type="ims" + modem_cognitive="true" + protocol="IPV6" + bearer_bitmask="1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17" + /> + + <apn carrier="T-Mobile IMS" + carrier_id = "1" + mcc="310" + mnc="260" + apn="ims" + type="ims" + modem_cognitive="true" + protocol="IPV6" + roaming_protocol="IPV6" + bearer="18" + /> + + <apn carrier="Google Fi - T" + carrier_id = "1989" + mcc="310" + mnc="260" + apn="h2g2" + user="none" + server="*" + password="none" + mmsc="http://mmsc1.g-mms.com/mms/wapenc" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="31026097" + mvno_type="IMSI" + /> + + <apn carrier="MetroPCS 260" + carrier_id = "1949" + mcc="310" + mnc="260" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D38" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 260" + carrier_id = "1949" + mcc="310" + mnc="260" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D38" + mvno_type="gid" + /> + + <apn carrier="SIMPLE" + carrier_id = "2078" + mcc="310" + mnc="260" + apn="simple" + type="default,mms,supl,hipri,fota" + protocol="IP" + roaming_protocol="IP" + mmsc="http://smpl.mms.msg.eng.t-mobile.com/mms/wapenc" + mvno_type="gid" + mvno_match_data="534D" + /> + + <apn carrier="TFWAP" + carrier_id = "2022" + mcc="310" + mnc="260" + apn="wap.tracfone" + type="default,mms,supl,hipri,fota" + protocol="IP" + roaming_protocol="IP" + mmsc="http://mms.tracfone.com" + mvno_type="gid" + mvno_match_data="deff" + /> + + <apn carrier="TFWAP" + carrier_id = "2022" + mcc="310" + mnc="260" + apn="wap.tracfone" + type="default,mms,supl,hipri,fota" + protocol="IP" + roaming_protocol="IP" + mmsc="http://mms.tracfone.com" + mvno_type="gid" + mvno_match_data="ddff" + /> + + <apn carrier="Consumer Cellular" + carrier_id = "2023" + mcc="310" + mnc="260" + apn="wholesale" + user="" + password="" + proxy="" + port="" + mmsc="http://wholesale.mmsmvno.com/mms/wapenc" + mmsproxy="" + mmsport="80" + type="default,mms,supl,hipri" + mvno_type="gid" + mvno_match_data="2AC9" + /> + + <apn carrier="T-Mobile US 270" + carrier_id = "1" + mcc="310" + mnc="270" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 270 DUN" + carrier_id = "1" + mcc="310" + mnc="270" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 270" + carrier_id = "1949" + mcc="310" + mnc="270" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 270" + carrier_id = "1949" + mcc="310" + mnc="270" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="agms" + carrier_id = "1187" + mcc="310" + mnc="280" + apn="agms" + type="default,supl" + /> + + <apn carrier="T-Mobile US 300" + carrier_id = "1" + mcc="310" + mnc="300" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 300 DUN" + carrier_id = "1" + mcc="310" + mnc="300" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 300" + carrier_id = "1949" + mcc="310" + mnc="300" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 300" + carrier_id = "1949" + mcc="310" + mnc="300" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="310" + mnc="30" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="310" + mnc="300" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="T-Mobile US 310" + carrier_id = "1" + mcc="310" + mnc="310" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 310 DUN" + carrier_id = "1" + mcc="310" + mnc="310" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 310" + carrier_id = "1949" + mcc="310" + mnc="310" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 310" + carrier_id = "1949" + mcc="310" + mnc="310" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="Cellular One NEAZ ISP" + carrier_id = "1796" + mcc="310" + mnc="320" + apn="isp.cellularoneaz.net" + type="default,supl" + /> + + <apn carrier="Cellular One ClearSky MMS" + carrier_id = "1796" + mcc="310" + mnc="320" + apn="wap.c1csky.net" + mmsc="http://mmsc.c1neaz.csky.us:6672" + mmsproxy="209.4.229.94" + mmsport="9401" + type="mms" + /> + + <apn carrier="alltel2" + mcc="310" + mnc="330" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="alltel2" + mmsc="http://mms.alltel.com/servlets/mms" + mmsproxy="mms.alltel.com" + mmsport="8080" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Alltel2 IMS" + mcc="310" + mnc="330" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="alltel2" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alltel2 IMS" + mcc="310" + mnc="330" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="alltel2" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Alltel2 FOTA" + mcc="310" + mnc="330" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="alltel2" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alltel2 FOTA" + mcc="310" + mnc="330" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="alltel2" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Alltel2" + mcc="310" + mnc="330" + apn="VZWINTERNET" + mmsc="http://mms.alltel.com/servlets/mms" + mmsproxy="mms.alltel.com" + mmsport="8080" + mvno_type="spn" + mvno_match_data="alltel2" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Alltel2" + mcc="310" + mnc="330" + apn="VZWINTERNET" + mmsc="http://mms.alltel.com/servlets/mms" + mmsproxy="mms.alltel.com" + mmsport="8080" + mvno_type="spn" + mvno_match_data="alltel2" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="pioneer" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="CdmaNai" + mmsc="http://mms1.zsend.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Pioneer IMS" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Pioneer IMS" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Pioneer FOTA" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Pioneer FOTA" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Pioneer" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWINTERNET" + mmsc="http://mms1.zsend.com" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Pioneer" + carrier_id = "1185" + mcc="310" + mnc="360" + apn="VZWINTERNET" + mmsc="http://mms1.zsend.com" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Cingular 380 ATT" + carrier_id = "1187" + mcc="310" + mnc="380" + apn="proxy" + mmsc="http://mmsc.cingular.com/" + mmsproxy="wireless.cingular.com" + type="default,supl,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="AWS MMS" + carrier_id = "1187" + mcc="310" + mnc="380" + apn="proxy" + mmsc="http://mmsc.mymmode.com" + mmsproxy="10.250.250.55" + mmsport="8080" + type="mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="AGMS Global" + carrier_id = "2030" + mcc="310" + mnc="380" + apn="agms.nl.gmm" + type="default" + mvno_type="gid" + mvno_match_data="50FF" + /> + + <apn carrier="GigSky" + carrier_id="2459" + mcc="310" + mnc="380" + apn="gigsky" + type="default" + mvno_type="spn" + mvno_match_data="GigSky" + /> + + <apn carrier="Celloneet MMS" + carrier_id = "1188" + mcc="310" + mnc="390" + apn="mms.celloneet.com" + user="user1@mms.celloneet.com" + password="celloneet" + mmsc="http://mms.celloneet.com/servlets/mms" + mmsproxy="63.99.231.135" + mmsport="8080" + type="mms" + /> + + <apn carrier="ATT Nextgenphone" + carrier_id = "1187" + mcc="310" + mnc="410" + apn="nxtgenphone" + type="default,mms,supl,fota,hipri" + mmsc="http://mmsc.mobile.att.net" + mmsproxy="proxy.mobile.att.net" + mmsport="80" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="IMS" + carrier_id = "1187" + mcc="310" + mnc="410" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="ATT Phone" + carrier_id = "1187" + mcc="310" + mnc="410" + apn="phone" + type="default,mms,supl,fota,hipri" + mmsc="http://mmsc.mobile.att.net" + mmsproxy="proxy.mobile.att.net" + mmsport="80" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="ATT WAP" + carrier_id = "1187" + mcc="310" + mnc="410" + apn="wap.cingular" + proxy="wireless.cingular.com" + port="80" + server="cingulargprs.com" + mmsc="http://mmsc.cingular.com/" + mmsproxy="wireless.cingular.com" + type="default,supl,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Defense Mobile" + carrier_id = "2029" + mcc="310" + mnc="410" + apn="PRODATA" + mmsc="http://mmsc.mobile.att.net" + mmsproxy="proxy.mobile.att.net" + mmsport="80" + type="default,mms,supl" + protocol="IP" + mtusize="1410" + mvno_type="gid" + mvno_match_data="60FF" + /> + + <apn carrier="TFDATA" + carrier_id = "2022" + mcc="310" + mnc="410" + apn="tfdata" + type="default,mms,supl,hipri,fota" + protocol="IP" + roaming_protocol="IP" + mmsc="http://mms-tf.net" + mmsproxy="mms3.tracfone.com" + mmsport="80" + mvno_type="gid" + mvno_match_data="deff" + /> + + <apn carrier="TFDATA" + carrier_id = "2022" + mcc="310" + mnc="410" + apn="tfdata" + type="default,mms,supl,hipri,fota" + protocol="IP" + roaming_protocol="IP" + mmsc="http://mms-tf.net" + mmsproxy="mms3.tracfone.com" + mmsport="80" + mvno_type="gid" + mvno_match_data="ddff" + /> + + <apn carrier="CBW Data" + carrier_id = "1190" + mcc="310" + mnc="420" + apn="wap.gocbw.com" + mmsc="http://mms.gocbw.com:8088/mms" + mmsproxy="216.68.79.202" + mmsport="80" + type="default,supl,mms" + /> + + <apn carrier="gci" + mcc="310" + mnc="430" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="gci" + mmsc="http://mmsc.akdt.dataonair.net:6672/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Gci IMS" + mcc="310" + mnc="430" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="gci" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gci IMS" + mcc="310" + mnc="430" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="gci" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Gci FOTA" + mcc="310" + mnc="430" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="gci" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gci FOTA" + mcc="310" + mnc="430" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="gci" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Gci" + mcc="310" + mnc="430" + apn="VZWINTERNET" + mmsc="http://mmsc.akdt.dataonair.net:6672/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="gci" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gci" + mcc="310" + mnc="430" + apn="VZWINTERNET" + mmsc="http://mmsc.akdt.dataonair.net:6672/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="gci" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Viaero Connect" + carrier_id = "1193" + mcc="310" + mnc="450" + apn="internet.vedge.com" + type="default,supl" + /> + + <apn carrier="Viaero MMS" + carrier_id = "1193" + mcc="310" + mnc="450" + apn="mms" + mmsc="http://mms.viaero.com" + mmsproxy="10.168.3.23" + mmsport="9401" + type="mms" + /> + + <apn carrier="DataConnect" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="isp.cingular" + type="default,supl" + /> + + <apn carrier="MediaNet" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="wap.cingular" + user="WAP@CINGULARGPRS.COM" + password="CINGULAR1" + mmsc="http://mmsc.cingular.com" + mmsproxy="66.209.11.32" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="nTelos Ota" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="admin.4g.ntelos.com" + type="admin,fota,ota" + bearer_bitmask="13" + mmsc="http://mms.ntelospcs.net" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="nTelos Ota" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="admin.4g.ntelos.com" + type="admin,fota,ota" + bearer_bitmask="14" + mmsc="http://mms.ntelospcs.net" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="nTelos Wireless" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="internet.4g.ntelos.com" + type="default,internet,supl,hipri,mms" + mmsc="http://mms.ntelospcs.net" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="nTelos Tether" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="tethering.4g.ntelos.com" + type="dun,pam" + bearer_bitmask="13" + mmsc="http://mms.ntelospcs.net" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="nTelos Tether" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="tethering.4g.ntelos.com" + type="dun,pam" + bearer_bitmask="14" + mmsc="http://mms.ntelospcs.net" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="nTelos Wireless" + carrier_id = "1893" + mcc="310" + mnc="470" + apn="CdmaNai" + mmsc="http://mms.ntelospcs.net/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="DataConnect" + carrier_id = "1195" + mcc="310" + mnc="480" + apn="isp.cingular" + type="default,supl" + /> + + <apn carrier="MediaNet" + carrier_id = "1195" + mcc="310" + mnc="480" + apn="wap.cingular" + user="WAP@CINGULARGPRS.COM" + password="CINGULAR1" + mmsc="http://mmsc.cingular.com" + mmsproxy="66.209.11.32" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="T-Mobile US 490" + carrier_id = "1" + mcc="310" + mnc="490" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 490 DUN" + carrier_id = "1" + mcc="310" + mnc="490" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 490" + carrier_id = "1949" + mcc="310" + mnc="490" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 490" + carrier_id = "1949" + mcc="310" + mnc="490" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="GoodCall Picture Message" + carrier_id = "1" + mcc="310" + mnc="490" + apn="good.call" + mmsc="http://mms.suncom.net:8088/mms" + mmsproxy="66.150.33.125" + mmsport="8080" + type="mms" + /> + + <apn carrier="Suncom MMS" + carrier_id = "1" + mcc="310" + mnc="490" + apn="mms" + mmsc="http://mms.suncom.net:8088/mms" + mmsproxy="66.150.33.125" + mmsport="8080" + type="mms" + /> + + <apn carrier="T-Mobile US 530" + carrier_id = "1" + mcc="310" + mnc="530" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 530 DUN" + carrier_id = "1" + mcc="310" + mnc="530" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 530" + carrier_id = "1949" + mcc="310" + mnc="530" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 530" + carrier_id = "1949" + mcc="310" + mnc="530" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="ATT Nextgenphone" + carrier_id = "1187" + mcc="310" + mnc="560" + apn="nxtgenphone" + mmsc="http://mmsc.mobile.att.net" + mmsproxy="proxy.mobile.att.net" + mmsport="80" + type="default,mms,supl,fota,hipri" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mtu="1410" + /> + + <apn carrier="IMS" + carrier_id = "1187" + mcc="310" + mnc="560" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="DobsonMMS" + carrier_id = "1187" + mcc="310" + mnc="560" + apn="dobsoncellularwap" + mmsc="http://mmsc" + mmsproxy="172.23.1.252" + mmsport="8799" + type="mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Cellular One Smartphone" + carrier_id = "1800" + mcc="310" + mnc="570" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cellular One MMS" + carrier_id = "1800" + mcc="310" + mnc="570" + apn="clearsky" + mmsc="http://mmsc.mtpcs.csky.us:6672/" + mmsproxy="209.4.229.229" + mmsport="9201" + type="mms" + /> + + <apn carrier="inland" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="CdmaNai" + mmsc="http://mms.inland3g.com/inland/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Inland IMS" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Inland IMS" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Inland FOTA" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Inland FOTA" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Inland" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWINTERNET" + mmsc="http://mms.inland3g.com/inland/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Inland" + carrier_id = "2011" + mcc="310" + mnc="580" + apn="VZWINTERNET" + mmsc="http://mms.inland3g.com/inland/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="CellularOne MMS" + carrier_id = "1" + mcc="310" + mnc="590" + apn="cellular1wap" + mmsc="http://mmsc" + mmsproxy="172.23.1.252" + mmsport="8799" + type="mms" + /> + + <apn carrier="T-Mobile US 590" + carrier_id = "1" + mcc="310" + mnc="590" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 590 DUN" + carrier_id = "1" + mcc="310" + mnc="590" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 590" + carrier_id = "1949" + mcc="310" + mnc="590" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 590" + carrier_id = "1949" + mcc="310" + mnc="590" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="cellcom" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="CdmaNai" + mmsc="http://mms.cellcom.com/cellcom/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Cellcom IMS" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cellcom IMS" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Cellcom FOTA" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cellcom FOTA" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Cellcom" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWINTERNET" + mmsc="http://mms.cellcom.com/cellcom/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cellcom" + carrier_id = "1802" + mcc="310" + mnc="600" + apn="VZWINTERNET" + mmsc="http://mms.cellcom.com/cellcom/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="EpicINT" + carrier_id = "1803" + mcc="310" + mnc="610" + apn="internet.epictouch" + type="default,supl" + /> + + <apn carrier="EpicMMS" + carrier_id = "1803" + mcc="310" + mnc="610" + apn="mms.epictouch" + mmsc="http://mmsc.westlinkcom.com/servlets/mms" + mmsproxy="63.99.231.135" + mmsport="8080" + type="mms" + /> + + <apn carrier="T-Mobile US 640" + carrier_id = "1" + mcc="310" + mnc="640" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 640 DUN" + carrier_id = "1" + mcc="310" + mnc="640" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + /> + + <apn carrier="MetroPCS 640" + carrier_id = "1949" + mcc="310" + mnc="640" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 640" + carrier_id = "1949" + mcc="310" + mnc="640" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="T-Mobile US 660" + carrier_id = "1" + mcc="310" + mnc="660" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 660 DUN" + carrier_id = "1" + mcc="310" + mnc="660" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 660" + carrier_id = "1949" + mcc="310" + mnc="660" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 660" + carrier_id = "1949" + mcc="310" + mnc="660" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="310" + mnc="69" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="547275554B3030656E" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="310" + mnc="69" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + mvno_type="gid" + mvno_match_data="54727555533030656E" + /> + + <apn carrier="Limitless" + carrier_id = "1808" + mcc="310" + mnc="690" + apn="limitless.us4g.com" + mmsc="http://mms.limitless.csky.us:6672/" + mmsproxy="209.4.229.79" + mmsport="9401" + /> + + <apn carrier="Rogers Internet" + carrier_id = "1811" + mcc="310" + mnc="720" + apn="internet.com" + user="" + password="" + proxy="10.128.1.69" + port="80" + type="default" + /> + + <apn carrier="Rogers Media" + carrier_id = "1811" + mcc="310" + mnc="720" + apn="media.com" + user="media" + password="mda01" + proxy="10.128.1.69" + port="80" + type="mms" + /> + + <apn carrier="appalachian" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="CdmaNai" + mmsc="http://mms.ekn.com" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Appalachian IMS" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Appalachian IMS" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Appalachian FOTA" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Appalachian FOTA" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Appalachian" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWINTERNET" + mmsc="http://mms.ekn.com" + mmsproxy="" + mmsport="80" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Appalachian" + carrier_id = "1813" + mcc="310" + mnc="750" + apn="VZWINTERNET" + mmsc="http://mms.ekn.com" + mmsproxy="" + mmsport="80" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + <apn carrier="Web 2" + carrier_id = "1815" + mcc="310" + mnc="770" + apn="i2.iwireless.com" + type="default,supl" + /> + + <apn carrier="Web 1" + carrier_id = "1815" + mcc="310" + mnc="770" + apn="wap1.iwireless.com" + proxy="209.4.229.31" + port="9401" + type="default,supl" + /> + + <apn carrier="Picture Messaging" + carrier_id = "1815" + mcc="310" + mnc="770" + apn="wap1.iwireless.com" + mmsc="http://mmsc.iwireless.dataonair.net:6672" + mmsproxy="209.4.229.31" + mmsport="9401" + type="mms" + /> + + <apn carrier="T-Mobile US 800" + carrier_id = "1" + mcc="310" + mnc="800" + apn="fast.t-mobile.com" + mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc" + type="default,supl,mms,ia" + protocol="IPV6" + roaming_protocol="IP" + mtu="1440" + /> + + <apn carrier="T-Mobile US 800 DUN" + carrier_id = "1" + mcc="310" + mnc="800" + apn="pcweb.tmobile.com" + user="none" + server="*" + password="none" + protocol="IP" + type="dun" + mtu="1440" + /> + + <apn carrier="MetroPCS 800" + carrier_id = "1949" + mcc="310" + mnc="800" + apn="fast.metropcs.com" + type="ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="MetroPCS 800" + carrier_id = "1949" + mcc="310" + mnc="800" + apn="fast.metropcs.com" + mmsc="http://metropcs.mmsmvno.com/mms/wapenc" + type="default,supl,mms" + protocol="IPV6" + roaming_protocol="IP" + mvno_match_data="6D" + mvno_type="gid" + /> + + <apn carrier="nepa" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="nepa" + mmsc="http://mmsc.c1nepa.csky.us:6672/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Nepa IMS" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nepa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nepa IMS" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nepa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nepa FOTA" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nepa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nepa FOTA" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nepa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nepa" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWINTERNET" + mmsc="http://mmsc.c1nepa.csky.us:6672/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nepa" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nepa" + carrier_id = "2325" + mcc="310" + mnc="820" + apn="VZWINTERNET" + mmsc="http://mmsc.c1nepa.csky.us:6672/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nepa" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Internet" + carrier_id = "1821" + mcc="310" + mnc="840" + apn="isp" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1821" + mcc="310" + mnc="840" + apn="mms" + mmsc="http://mms.edgemobile.net/mmsc" + mmsproxy="12.108.12.13" + mmsport="3128" + type="mms" + /> + + <apn carrier="Edge MMS Prepay" + carrier_id = "1821" + mcc="310" + mnc="840" + apn="ppmms" + mmsc="http://mms.edgemobile.net/mmsc" + mmsproxy="12.108.12.13" + mmsport="3128" + type="mms" + /> + + <apn carrier="DTC dtcwap" + carrier_id = "1825" + mcc="310" + mnc="880" + apn="wapdtcw.com" + type="default" + proxy="204.181.155.218" + port="8080" + /> + + <apn carrier="DTC MMS" + carrier_id = "1825" + mcc="310" + mnc="880" + apn="mms.adv.com" + mmsc="http://mms.iot1.com/advantage/mms.php" + type="mms" + /> + + <apn carrier="midrivers" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="CdmaNai" + mmsc="http://mmsc.midrivers.csky.us:6672/" + mmsproxy="209.4.229.27" + mmsport="9401" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Midrivers IMS" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Midrivers IMS" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Midrivers FOTA" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Midrivers FOTA" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Midrivers" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWINTERNET" + mmsc="http://mmsc.midrivers.csky.us:6672/" + mmsproxy="209.4.229.27" + mmsport="9401" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Midrivers" + carrier_id = "1827" + mcc="310" + mnc="900" + apn="VZWINTERNET" + mmsc="http://mmsc.midrivers.csky.us:6672/" + mmsproxy="209.4.229.27" + mmsport="9401" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + <apn carrier="WOW_WAP" + carrier_id = "1828" + mcc="310" + mnc="910" + apn="wap.firstcellular.com" + mmsc="mms.firstcellular.net/mmsc" + mmsproxy="10.101.1.5" + mmsport="3128" + type="default,supl,mms" + /> + + <apn carrier="jamesvalley" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="CdmaNai" + mmsc="http://m.iot1.com/jamesvalley/mms.php" + mmsproxy="m.iot1.com" + mmsport="9201" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Jamesvalley IMS" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Jamesvalley IMS" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Jamesvalley FOTA" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Jamesvalley FOTA" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Jamesvalley" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWINTERNET" + mmsc="http://m.iot1.com/jamesvalley/mms.php" + mmsproxy="m.iot1.com" + mmsport="9201" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Jamesvalley" + carrier_id = "1829" + mcc="310" + mnc="920" + apn="VZWINTERNET" + mmsc="http://m.iot1.com/jamesvalley/mms.php" + mmsproxy="m.iot1.com" + mmsport="9201" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="coppervalley" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="CdmaNai" + mmsc="http://cvwmms.com/servlets/mms" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Coppervalley IMS" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Coppervalley IMS" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Coppervalley FOTA" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Coppervalley FOTA" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Copper Valley" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWINTERNET" + mmsc="http://cvwmms.com/servlets/mms" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Copper Valley" + carrier_id = "1830" + mcc="310" + mnc="930" + apn="VZWINTERNET" + mmsc="http://cvwmms.com/servlets/mms" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="nntcwire" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="nntcwire" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Nntcwire IMS" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nntcwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nntcwire IMS" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nntcwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nntcwire FOTA" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nntcwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nntcwire FOTA" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nntcwire" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nntcwire" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nntcwire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nntcwire" + carrier_id = "2324" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nntcwire" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="silverstar" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="silverstar" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Silverstar IMS" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="silverstar" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Silverstar IMS" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="silverstar" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Silverstar FOTA" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="silverstar" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Silverstar FOTA" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="silverstar" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Silverstar" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="silverstar" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Silverstar" + carrier_id = "2323" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="silverstar" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="snakeriver" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="snakeriver" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Snakeriver IMS" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="snakeriver" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Snakeriver IMS" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="snakeriver" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Snakeriver FOTA" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="snakeriver" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Snakeriver FOTA" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="snakeriver" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Snakeriver" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="snakeriver" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Snakeriver" + carrier_id = "2322" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="snakeriver" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="southcentral" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="southcentral" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Southcentral IMS" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="southcentral" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Southcentral IMS" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="southcentral" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Southcentral FOTA" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="southcentral" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Southcentral FOTA" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="southcentral" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Southcentral" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="southcentral" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Southcentral" + carrier_id = "2321" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="southcentral" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="strata" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="strata" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Strata IMS" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="strata" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Strata IMS" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="strata" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Strata FOTA" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="strata" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Strata FOTA" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="strata" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="strata" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="strata" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="strata" + carrier_id = "2320" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="strata" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="syringa" + mcc="310" + mnc="960" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="syringa" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Syringa IMS" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="syringa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Syringa IMS" + mcc="310" + mnc="960" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="syringa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Syringa FOTA" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="syringa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Syringa FOTA" + mcc="310" + mnc="960" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="syringa" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Syringa" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="syringa" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Syringa" + mcc="310" + mnc="960" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="syringa" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="thumbcellular" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="CdmaNai" + mmsc="http://mms.thumbcell.com/thumb/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Thumb IMS" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Thumb IMS" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Thumb FOTA" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Thumb FOTA" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Thumbcellular" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWINTERNET" + mmsc="http://mms.thumbcell.com/thumb/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Thumbcellular" + carrier_id = "1241" + mcc="311" + mnc="050" + apn="VZWINTERNET" + mmsc="http://mms.thumbcell.com/thumb/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="elementmobile" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="elementmobile" + mmsc="http://mms.elementmobile.net" + mmsproxy="" + mmsport="8080" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Elementmobile IMS" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="elementmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Elementmobile IMS" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="elementmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Elementmobile FOTA" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="elementmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Elementmobile FOTA" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="elementmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Elementmobile" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWINTERNET" + mmsc="http://mms.elementmobile.net" + mmsproxy="" + mmsport="8080" + mvno_type="spn" + mvno_match_data="elementmobile" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Elementmobile" + carrier_id = "2319" + mcc="311" + mnc="070" + apn="VZWINTERNET" + mmsc="http://mms.elementmobile.net" + mmsproxy="" + mmsport="8080" + mvno_type="spn" + mvno_match_data="elementmobile" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="PINE WAP" + carrier_id = "1244" + mcc="311" + mnc="080" + apn="PINE" + mmsc="http://69.8.34.146/mms/" + mmsproxy="69.8.34.146" + mmsport="9401" + type="default,mms" + /> + + <apn carrier="NexTech Wireless" + carrier_id = "2255" + mcc="311" + mnc="100" + authtype="3" + type="mms" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="sprocket" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="sprocket" + mmsc="http://mms.sprocketwireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Sprocket IMS" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="sprocket" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Sprocket IMS" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="sprocket" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Sprocket FOTA" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="sprocket" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Sprocket FOTA" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="sprocket" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Sprocket" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWINTERNET" + mmsc="http://mms.sprocketwireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="sprocket" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Sprocket" + carrier_id = "2318" + mcc="311" + mnc="140" + apn="VZWINTERNET" + mmsc="http://mms.sprocketwireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="sprocket" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="ISP" + carrier_id = "1833" + mcc="311" + mnc="190" + apn="isp.cellular1.net" + type="default,supl" + /> + + <apn carrier="Tether" + carrier_id = "1833" + mcc="311" + mnc="190" + apn="broadband.cellular1.net" + type="dun" + /> + + <apn carrier="MMS" + carrier_id = "1833" + mcc="311" + mnc="190" + apn="mms.cellular1.net" + mmsc="http://mms.cellular1.net" + mmsproxy="10.10.0.97" + mmsport="9201" + type="mms" + /> + + <apn carrier="Farmers GPRS" + carrier_id = "1835" + mcc="311" + mnc="210" + apn="internet.farmerswireless.com" + type="default,supl" + /> + + <apn carrier="Farmers MMS" + carrier_id = "1835" + mcc="311" + mnc="210" + apn="mms.farmers.com" + mmsc="172.16.0.37:8514" + type="mms" + /> + + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="220" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + authtype="3" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="220" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="220" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="221" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="221" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="220" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="221" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="221" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="221" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="222" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="222" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="222" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="223" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="223" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="223" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="224" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="224" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="224" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="225" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="225" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + carrier_enabled="true" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="225" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + carrier_enabled="true" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="226" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="226" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="226" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="227" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="227" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="227" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="228" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="228" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="228" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="229" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="229" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="229" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="CSpire ota" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="admin.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + type="admin,fota,ota" + bearer_bitmask="14" + protocol="IPV4V6" + /> + + <apn carrier="CSpire ota" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="admin.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + type="admin,fota,ota" + bearer_bitmask="13" + protocol="IPV4V6" + /> + + <apn carrier="CSpire internet" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="internet.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + type="default,internet,mms" + protocol="IPV4V6" + /> + + <apn carrier="CSpire tether" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="tethering.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + type="dun,pam" + bearer_bitmask="13" + protocol="IPV4V6" + /> + + <apn carrier="CSpire tether" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="tethering.cs4glte.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://pix.cspire.com" + type="dun,pam" + bearer_bitmask="14" + protocol="IPV4V6" + /> + + <apn carrier="CSpire" + carrier_id = "1836" + mcc="311" + mnc="230" + apn="CdmaNai" + mmsc="http://pix.cspire.com/servlets/mms" + mmsproxy="66.175.144.91" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="leaco" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="CdmaNai" + mmsc="http://204.181.155.217/mms/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Leaco IMS" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Leaco IMS" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Leaco FOTA" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Leaco FOTA" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Leaco" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWINTERNET" + mmsc="http://204.181.155.217/mms/" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Leaco" + carrier_id = "1842" + mcc="311" + mnc="310" + apn="VZWINTERNET" + mmsc="http://204.181.155.217/mms/" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="illinoisvalley" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="CdmaNai" + mmsc="http://mms.iot1.com/ivc/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Illinois IMS" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Illinois IMS" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Illinois FOTA" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Illinois FOTA" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Illinois valley" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/ivc/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Illinois valley" + carrier_id = "1263" + mcc="311" + mnc="340" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/ivc/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="nemont" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="nemont" + mmsc="http://mms.nemont.mobi/mms/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Nemont IMS" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nemont" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nemont IMS" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="nemont" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nemont FOTA" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nemont" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nemont FOTA" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="nemont" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Nemont" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWINTERNET" + mmsc="http://mms.nemont.mobi/mms/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nemont" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Nemont" + carrier_id = "2317" + mcc="311" + mnc="350" + apn="VZWINTERNET" + mmsc="http://mms.nemont.mobi/mms/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="nemont" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="GCI WEB" + carrier_id = "1843" + mcc="311" + mnc="370" + apn="web.gci" + type="default,supl" + /> + + <apn carrier="GCI MMS" + carrier_id = "1843" + mcc="311" + mnc="370" + apn="mms.gci" + proxy="24.237.158.34" + port="9201" + mmsc="http://mmsc.gci.net" + mmsproxy="24.237.158.34" + mmsport="9201" + type="mms" + /> + + <apn carrier="Ericsson Test-SIM Internet" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM Internet" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWINTERNET" + mmsc="http://mms.vtext.com/servlets/mms" + type="default,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM FOTA" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM FOTA" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM IMS" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM IMS" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM CBS" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWAPP" + mmsc="http://mms.vtext.com/servlets/mms" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="Ericsson Test-SIM CBS" + carrier_id = "1845" + mcc="311" + mnc="390" + apn="VZWAPP" + mmsc="http://mms.vtext.com/servlets/mms" + type="cbs,mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <apn carrier="chatmobrsa2" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="CdmaNai" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Chatmobrsa2 IMS" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa2 IMS" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chatmobrsa2 FOTA" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa2 FOTA" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chatmobrsa2" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWINTERNET" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa2" + carrier_id = "1846" + mcc="311" + mnc="410" + apn="VZWINTERNET" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="northwestcell" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="CdmaNai" + mmsc="http://mms.nwmcell.com/mms/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="NW IMS" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="NW IMS" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="NW FOTA" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="NW FOTA" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Northwestcell" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWINTERNET" + mmsc="http://mms.nwmcell.com/mms/" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Northwestcell" + carrier_id = "1847" + mcc="311" + mnc="420" + apn="VZWINTERNET" + mmsc="http://mms.nwmcell.com/mms/" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="chatmobrsa1" + mcc="311" + mnc="430" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Chatmobrsa1 IMS" + mcc="311" + mnc="430" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa1 IMS" + mcc="311" + mnc="430" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chatmobrsa1 FOTA" + mcc="311" + mnc="430" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa1 FOTA" + mcc="311" + mnc="430" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chatmobrsa1" + mcc="311" + mnc="430" + apn="VZWINTERNET" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobrsa1" + mcc="311" + mnc="430" + apn="VZWINTERNET" + mmsc="http://mmsc.hawkeyeswitch.net/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="chatmobrsa1" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="bluegrass" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="CdmaNai" + mmsc="http://mms.iot1.com/bluegrass/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Bluegrass IMS" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluegrass IMS" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Bluegrass FOTA" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluegrass FOTA" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Bluegrass" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/bluegrass/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Bluegrass" + carrier_id = "1849" + mcc="311" + mnc="440" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/bluegrass/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="ptci" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="CdmaNai" + mmsc="http://mmsc.ptci.net" + mmsproxy="" + mmsport="6672" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Ptci IMS" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Ptci IMS" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Ptci FOTA" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Ptci FOTA" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Ptci" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWINTERNET" + mmsc="http://mmsc.ptci.net" + mmsproxy="" + mmsport="6672" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Ptci" + carrier_id = "1850" + mcc="311" + mnc="450" + apn="VZWINTERNET" + mmsc="http://mmsc.ptci.net" + mmsproxy="" + mmsport="6672" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <!-- Need two APNs for CDMA technologies: a default that is used normally --> + <!-- and a second APN to be used when DUN is required. Even though the --> + <!-- parameters appear the same, the profileID sent to the radio when requesting --> + <!-- a DUN connection will be different --> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="internet" + authtype="3" + type="default,mms,supl,fota,cbs" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + user_visible="false" + /> + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="internet" + authtype="3" + type="default,mms,supl,fota,cbs,dun" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + profile_id="1" + user_visible="false" + /> + + <!-- bearer 1, 2, 3, 9, 10, 11, 13, 14, 15 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="VZWINTERNET" + type="default,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="1|2|3|9|10|11|13|14|15" + profile_id="0" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + /> + + <!-- bearer 1, 2, 3, 9, 10, 11, 13, 14, 15 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="1|2|3|9|10|11|13|14|15" + profile_id="3" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + user_visible="false" + /> + + <!-- bearer 1, 2, 3, 9, 10, 11, 13, 14, 15 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="IMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="1|2|3|9|10|11|13|14|15" + profile_id="2" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + user_visible="false" + /> + + <!-- bearer 1, 2, 3, 9, 10, 11, 13, 14, 15 --> + <apn carrier="Verizon" + carrier_id = "1839" + mcc="311" + mnc="480" + apn="VZWAPP" + type="cbs,mms" + mmsc="http://mms.vtext.com/servlets/mms" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="1|2|3|9|10|11|13|14|15" + profile_id="4" + modem_cognitive="true" + max_conns="1023" + max_conns_time="300" + user_visible="false" + /> + + <apn carrier="24-7 WAP" + carrier_id = "1854" + mcc="311" + mnc="500" + apn="wap" + mmsc="http://mmsc.ctc.csky.us:6672" + mmsproxy="09.4.229.46" + mmsport="9201" + /> + + <apn carrier="Mosaic WAP" + carrier_id = "2316" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Mosaic Mobile" + /> + + <apn carrier="Mosaic WAP AT&T" + carrier_id = "2316" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Mosaic RPA" + /> + + <apn carrier="Mosaic WAP T-Mobile" + carrier_id = "2316" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Mosaic RPT" + /> + + <apn carrier="Mosaic WAP Other networks" + carrier_id = "2316" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Mosaic RPO" + /> + + <apn carrier="Norvado" + carrier_id = "2315" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Norvado Wireless" + /> + + <apn carrier="Norvado AT&T" + carrier_id = "2315" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Norvado Wireless RPA" + /> + + <apn carrier="Norvado T-Mobile" + carrier_id = "2315" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Norvado Wireless RPT" + /> + + <apn carrier="Norvado Other networks" + carrier_id = "2315" + mcc="311" + mnc="500" + apn="wap" + type="default,mms" + mmsc="http://mmsc.ctc.csky.us:6672/" + mmsproxy="209.4.229.46" + mmsport="9201" + mvno_type="spn" + mvno_match_data="Norvado Wireless RPO" + /> + + <apn carrier="Blaze" + carrier_id = "1857" + mcc="311" + mnc="530" + apn="mms.mymobiletxt.com" + type="default,mms" + mmsc="http://mms2.mymobiletxt.net" + /> + + <apn carrier="Duet Internet" + carrier_id = "1857" + mcc="311" + mnc="530" + apn="wap.mymobiletxt.com" + type="default,mms" + protocol="IP" + mmsc="http://172.16.16.103/mms/" + mmsproxy="172.16.16.102" + mmsport="8080" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="580" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="580" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + carrier_id = "1952" + mcc="311" + mnc="580" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="581" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="581" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="581" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="582" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="582" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="582" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="583" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="583" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="583" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="584" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="584" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="584" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="585" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="585" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="585" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="586" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="586" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="586" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="587" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="587" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="587" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="588" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="588" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="588" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="589" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + mtu="1422" + /> + + <apn carrier="U.S. Cellular" + mcc="311" + mnc="589" + apn="usccinternet" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + mtu="1422" + /> + + <!-- bearer 4, 5, 6, 7, 8, 12 --> + <apn carrier="U.S. Cellular" + mcc="311" + mnc="589" + mmsc="http://mmsc1.uscc.net/mmsc/MMS" + type="default,mms,dun,hipri,fota" + authtype="3" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="4|5|6|7|8|12" + mtu="1422" + /> + + <apn carrier="gsc" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="gsc" + mmsc="http://mmsc1.gscdata.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Gsc IMS" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="gsc" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gsc IMS" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="gsc" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Gsc FOTA" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="gsc" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gsc FOTA" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="gsc" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Gsc" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWINTERNET" + mmsc="http://mmsc1.gscdata.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="gsc" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Gsc" + carrier_id = "2288" + mcc="311" + mnc="590" + apn="VZWINTERNET" + mmsc="http://mmsc1.gscdata.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="gsc" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="cox" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="CdmaNai" + mmsc="http://mms.cox.net/cox/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Cox IMS" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cox IMS" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWIMS" + type="ims,ia" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Cox FOTA" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cox FOTA" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWADMIN" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Cox" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWINTERNET" + mmsc="http://mms.cox.net/cox/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Cox" + carrier_id = "1910" + mcc="311" + mnc="600" + apn="VZWINTERNET" + mmsc="http://mms.cox.net/cox/mms.php" + mmsproxy="" + mmsport="" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="srtcomm" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="srtcomm" + mmsc="http://mms.iot1.com/srt/mms.php" + mmsproxy="mms.iot1.com" + mmsport="9201" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Srtcomm IMS" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="srtcomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Srtcomm IMS" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="srtcomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Srtcomm FOTA" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="srtcomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Srtcomm FOTA" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="srtcomm" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Srtcomm" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/srt/mms.php" + mmsproxy="mms.iot1.com" + mmsport="9201" + mvno_type="spn" + mvno_match_data="srtcomm" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Srtcomm" + carrier_id = "2158" + mcc="311" + mnc="610" + apn="VZWINTERNET" + mmsc="http://mms.iot1.com/srt/mms.php" + mmsproxy="mms.iot1.com" + mmsport="9201" + mvno_type="spn" + mvno_match_data="srtcomm" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="unitedwireless" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="unitedwireless" + mmsc="http://mms.unitedwireless.com/united/mms.php" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="United IMS" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="unitedwireless" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="United IMS" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="unitedwireless" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="United FOTA" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="unitedwireless" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="United FOTA" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="unitedwireless" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Unitedwireless" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWINTERNET" + mmsc="http://mms.unitedwireless.com/united/mms.php" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="unitedwireless" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Unitedwireless" + carrier_id = "2159" + mcc="311" + mnc="650" + apn="VZWINTERNET" + mmsc="http://mms.unitedwireless.com/united/mms.php" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="unitedwireless" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Pine Belt" + carrier_id = "2160" + mcc="311" + mnc="670" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Pine Belt" + carrier_id = "2160" + mcc="311" + mnc="670" + apn="lte.ota.pinebelt.net" + type="fota" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Pine Belt" + carrier_id = "2160" + mcc="311" + mnc="670" + apn="lte.internet.pinebelt.net" + mmsc="http://mmsc.pinebelt.net:6672/" + mmsproxy="" + mmsport="" + type="default,mms,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Pine Belt" + carrier_id = "2160" + mcc="311" + mnc="670" + apn="lte.tether.pinebelt.net" + mmsc="http://mmsc.pinebelt.net:6672/" + mmsproxy="" + mmsport="" + type="dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="TelAlaska Cellular" + carrier_id = "2256" + mcc="311" + mnc="740" + apn="akcell.mobi" + type="default" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Cleartalk" + carrier_id = "2257" + mcc="311" + mnc="750" + apn="CdmaNai" + authtype="3" + type="default,mms,supl,dun" + mmsc="http://mms.cleartalk.us/cleartalk/mms.php" + protocol="IPV4V6" + bearer_bitmask="6" + /> + <apn carrier="ClearTalk LTE" + carrier_id = "2257" + mcc="311" + mnc="750" + apn="home.netamerica.com" + type="default,mms,supl,dun" + bearer_bitmask="14" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mmsc="http://mms.cleartalk.us/cleartalk/mms.php" + mtu="1428" + /> + + <apn carrier="Sprint" + carrier_id = "1788" + mcc="311" + mnc="882" + apn="internet.curiosity.sprint.com" + type="default" + protocol="IPV4V6" + network_type_bitmask="13" + /> + <apn carrier="Sprint" + carrier_id = "1788" + mcc="311" + mnc="882" + apn="arm.ericsson.iot" + type="admin" + protocol="IPV4V6" + network_type_bitmask="13" + /> + + <apn carrier="MobileNation" + carrier_id = "2258" + mcc="311" + mnc="910" + apn="mymn4g.net" + server="*" + mmsport="8081" + mmsproxy="mms.mymn3g.net" + mmsc="http://mms.mymn3g.net" + type="default,internet,admin,fota,dun,mms" + protocol="IPV4V6" + /> + + <apn carrier="charitonvalley" + mcc="311" + mnc="920" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="charitonvalley" + mmsc="http://mms.cvalley.net" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Chariton IMS" + mcc="311" + mnc="920" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="charitonvalley" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chariton IMS" + mcc="311" + mnc="920" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="charitonvalley" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chariton FOTA" + mcc="311" + mnc="920" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="charitonvalley" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chariton FOTA" + mcc="311" + mnc="920" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="charitonvalley" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Chariton valley" + mcc="311" + mnc="920" + apn="VZWINTERNET" + mmsc="http://mms.cvalley.net" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="charitonvalley" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chariton valley" + mcc="311" + mnc="920" + apn="VZWINTERNET" + mmsc="http://mms.cvalley.net" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="charitonvalley" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Syringa Wireless" + carrier_id = "2259" + mcc="311" + mnc="930" + apn="internet.syringawireless.com" + server="*" + mmsport="80" + mmsproxy="" + mmsc="http://mms.rinawireless.com" + type="default,internet,admin,fota,dun,mms" + protocol="IPV4V6" + /> + + <apn carrier="custer" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="custer" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Custer IMS" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="custer" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Custer IMS" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="custer" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Custer FOTA" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="custer" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Custer FOTA" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="custer" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Custer" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="custer" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Custer" + carrier_id = "2162" + mcc="312" + mnc="040" + apn="VZWINTERNET" + mmsc="http://mms.rinawireless.com" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="custer" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="chatmobility" + mcc="312" + mnc="160" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="chatmobility" + mmsc="http://mms.chatmobility.com/mms/" + mmsproxy="" + mmsport="80" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Chatmobility IMS" + mcc="312" + mnc="160" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="chatmobility" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Chatmobility IMS" + mcc="312" + mnc="160" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="chatmobility" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="chatmobility FOTA" + mcc="312" + mnc="160" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="chatmobility" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="chatmobility FOTA" + mcc="312" + mnc="160" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="chatmobility" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="chatmobility" + mcc="312" + mnc="160" + apn="VZWINTERNET" + mmsc="http://mms.chatmobility.com/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="chatmobility" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="chatmobility" + mcc="312" + mnc="160" + apn="VZWINTERNET" + mmsc="http://mms.chatmobility.com/mms/" + mmsproxy="" + mmsport="80" + mvno_type="spn" + mvno_match_data="chatmobility" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="NexTech Ota" + carrier_id = "2260" + mcc="312" + mnc="420" + apn="admin.lte.ntwls.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + type="admin,fota,ota" + bearer_bitmask="14" + protocol="IP" + /> + + <apn carrier="NexTech Ota" + carrier_id = "2260" + mcc="312" + mnc="420" + apn="admin.lte.ntwls.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + type="admin,fota,ota" + bearer_bitmask="13" + protocol="IP" + /> + + <apn carrier="NexTech Wireless" + carrier_id = "2260" + mcc="312" + mnc="420" + apn="internet.lte.ntwls.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + type="default,internet,supl,hipri,mms" + protocol="IPV4V6" + /> + + <apn carrier="NexTech Tether" + carrier_id = "2260" + mcc="312" + mnc="420" + apn="modem.lte.ntwls.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + type="dun,pam" + bearer_bitmask="14" + protocol="IPV4V6" + /> + + <apn carrier="NexTech Tether" + carrier_id = "2260" + mcc="312" + mnc="420" + apn="modem.lte.ntwls.com" + server="*" + mmsport="" + mmsproxy="" + mmsc="http://mms.ntwls.net/nex-tech/mms.php" + type="dun,pam" + bearer_bitmask="13" + protocol="IPV4V6" + /> + + <apn carrier="Blue Wireless" + carrier_id = "2261" + mcc="312" + mnc="570" + apn="Blue Hotspot" + server="*" + mmsport="8514" + mmsproxy="" + user="%M@dun.bluehandset.com" + password="wirelessblue" + mmsc="http://mms.blueunlimited.com" + type="default,dun,mms" + protocol="IPV4V6" + /> + + <apn carrier="openmobile" + mcc="330" + mnc="000" + apn="CdmaNai" + mvno_type="spn" + mvno_match_data="openmobile" + mmsc="http://mms.openmobilepr.com:1981/" + mmsproxy="" + mmsport="" + type="mms" + carrier_enabled="false" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="6" + /> + + <apn carrier="Openmobile IMS" + mcc="330" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="openmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Openmobile IMS" + mcc="330" + mnc="000" + apn="VZWIMS" + type="ims,ia" + mvno_type="spn" + mvno_match_data="openmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Openmobile FOTA" + mcc="330" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="openmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Openmobile FOTA" + mcc="330" + mnc="000" + apn="VZWADMIN" + type="fota" + mvno_type="spn" + mvno_match_data="openmobile" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Openmobile" + mcc="330" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.openmobilepr.com:1981/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="openmobile" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="13" + /> + + <apn carrier="Openmobile" + mcc="330" + mnc="000" + apn="VZWINTERNET" + mmsc="http://mms.openmobilepr.com:1981/" + mmsproxy="" + mmsport="" + mvno_type="spn" + mvno_match_data="openmobile" + type="default,mms,dun,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Puerto Rico:Claro:LTE" + carrier_id = "1955" + mcc="330" + mnc="110" + apn="lte.claropr.com" + type="default" + authtype="1" + /> + + <apn carrier="Puerto Rico:Claro:Banda Ancha" + carrier_id = "1955" + mcc="330" + mnc="110" + apn="lte.claropr.com" + type="dun" + authtype="1" + /> + + <apn carrier="MMS CLARO" + carrier_id = "1955" + mcc="330" + mnc="110" + apn="mmslte.claropr.com" + mmsproxy="10.50.38.3" + mmsport="8799" + mmsc="http://mmsg.claropr.com:10021/mmsc" + authtype='1' + type="mms" + /> + + + <apn carrier="Internet" + carrier_id = "1913" + mcc="334" + mnc="020" + apn="internet.itelcel.com" + user="webgprs" + password="webgprs2002" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Mensajes Multimedia" + carrier_id = "1913" + mcc="334" + mnc="020" + apn="mms.itelcel.com" + user="mmsgprs" + password="mmsgprs2003" + mmsc="http://mms.itelcel.com/servlets/mms" + mmsproxy="148.233.151.240" + mmsport="8080" + authtype="1" + type="mms" + /> + + + <apn carrier="Movistar INTERNET" + carrier_id = "1914" + mcc="334" + mnc="03" + apn="internet.movistar.mx" + user="movistar" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1914" + mcc="334" + mnc="03" + apn="mms.movistar.mx" + user="movistar" + password="movistar" + mmsc="http://mms.movistar.mx" + mmsproxy="10.2.20.1" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1914" + mcc="334" + mnc="030" + apn="internet.movistar.mx" + user="movistar" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1914" + mcc="334" + mnc="030" + apn="mms.movistar.mx" + user="movistar" + password="movistar" + mmsc="http://mms.movistar.mx" + mmsproxy="10.2.20.1" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Iusacell Internet" + carrier_id = "1915" + mcc="334" + mnc="050" + apn="web.iusacellgsm.mx" + user="iusacellgsm" + password="iusacellgsm" + type="default,supl" + /> + + <apn carrier="Iusacell MMS" + carrier_id = "1915" + mcc="334" + mnc="050" + apn="mms.iusacellgsm.mx" + user="mmsiusacellgsm" + password="mmsiusacellgsm" + mmsc="http://mms.iusacell3g.com/" + type="mms" + /> + + <apn carrier="Modem" + mcc="334" + mnc="50" + authtype="1" + type="dun" + user="iusacellgsm" + password="iusacellgsm" + apn="modem.iusacellgsm.mx" + /> + + <apn carrier='Localización' + carrier_id = "1912" + mcc='334' + mnc='090' + apn='location.nexteldata.com.mx' + server='http://supl.nexteldata.com.mx' + authtype='0' + type='supl' + port='7275' + /> + + <apn carrier='MMS' + carrier_id = "1912" + mcc='334' + mnc='090' + apn='mms.nexteldata.com.mx' + authtype='0' + mmsc='http://3gmms.nexteldata.com.mx' + mmsproxy='129.192.129.104' + mmsport='8080' + type='mms' + /> + + <apn carrier='Internet' + carrier_id = "1912" + mcc='334' + mnc='090' + apn='modem.nexteldata.com.mx' + authtype='0' + type='dun' + /> + + <apn carrier='Navegación' + carrier_id = "1912" + mcc='334' + mnc='090' + apn='wap.nexteldata.com.mx' + authtype='0' + type='default' + /> + + <apn carrier="INTERNET Digicel" + carrier_id = "1577" + mcc="338" + mnc="05" + apn="web" + type="default,supl" + /> + + <apn carrier="MMS Digicel" + carrier_id = "1577" + mcc="338" + mnc="05" + apn="wap" + mmsproxy="172.16.7.12" + mmsport="8080" + mmsc="http://mms.digicelgroup.com" + type="mms" + /> + + <apn carrier="INTERNET Digicel" + carrier_id = "1577" + mcc="338" + mnc="050" + apn="web" + type="default,supl" + /> + + <apn carrier="MMS Digicel" + carrier_id = "1577" + mcc="338" + mnc="050" + apn="wap" + mmsproxy="172.16.7.12" + mmsport="8080" + mmsc="http://mms.digicelgroup.com" + type="mms" + /> + + <apn carrier="Lime Internet Postpaid" + carrier_id = "2224" + mcc="338" + mnc="18" + apn="internet" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + carrier_id = "2224" + mcc="338" + mnc="18" + apn="multimedia" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier="Lime Internet Prepaid" + carrier_id = "2224" + mcc="338" + mnc="18" + apn="ppinternet" + type="default,supl" + /> + + <apn carrier="Lime Prepaid MMS" + carrier_id = "2224" + mcc="338" + mnc="18" + apn="ppmms" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier="Lime Internet Postpaid" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="internet" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="multimedia" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier="Lime Internet Prepaid" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="ppinternet" + type="default,supl" + /> + + <apn carrier="Lime Prepaid MMS" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="ppmms" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier="Claro Web" + carrier_id = "2263" + mcc="338" + mnc="070" + apn="internet.ideasclaro.com.jm" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Claro MMS" + carrier_id = "2263" + mcc="338" + mnc="070" + apn="mms.ideasclaro.com.jm" + user="" + password="" + mmsproxy="190.80.147.118" + mmsport="8080" + mmsc="http://mms.ideasclaro.com.jm/mms/wapenc" + authtype="1" + type="mms" + /> + + <apn carrier="Lime Internet Postpaid" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + carrier_id = "2224" + mcc="338" + mnc="180" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + authtype="1" + type="mms" + /> + + <apn carrier="Orange World Caraïbe" + carrier_id = "742" + mcc="340" + mnc="01" + apn="orangeweb" + user="orange" + password="orange" + type="default,supl" + /> + + <apn carrier="Orange MMS Caraïbe" + carrier_id = "742" + mcc="340" + mnc="01" + apn="orangewap" + user="orange" + password="orange" + mmsc="http://193.251.160.246/servlets/mms" + mmsproxy="10.0.0.10" + mmsport="8082" + type="mms" + /> + + <apn carrier="Orangeweb" + carrier_id = "742" + mcc="340" + mnc="01" + apn="orangeweb" + user="orange" + password="orange" + authtype="1" + type="dun" + /> + + <apn carrier="Digicel Web" + carrier_id = "745" + mcc="340" + mnc="20" + apn="web.digicelfr.com" + mmsc="http://mmc.digiceltt.com/servlets/mms" + mmsproxy="172.20.6.12" + mmsport="8080" + type="default,mms,supl" + /> + + <apn carrier="Lime Internet Postpaid" + mcc="342" + mnc="60" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="342" + mnc="60" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Barbado:Lime:Internet' + carrier_id = "1360" + mcc='342' + mnc='600' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier="Barbados:Lime:Mms" + carrier_id = "1360" + mcc="342" + mnc="600" + apn="multimedia" + authtype="1" + mmsc="http://mmsc" + mmsproxy="10.20.5.34" + mmsport="8799" + type="mms" + /> + + <apn carrier='Barbado:Lime:Modem' + carrier_id = "1360" + mcc='342' + mnc='600' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="344" + mnc="92" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="344" + mnc="92" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Antigua:Lime:Internet' + carrier_id = "1325" + mcc='344' + mnc='920' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Antigua:Lime:Mms' + carrier_id = "1325" + mcc='344' + mnc='920' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Antigua:Lime:Modem' + carrier_id = "1325" + mcc='344' + mnc='920' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="346" + mnc="14" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="346" + mnc="14" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Cayman Islands:Lime:Internet' + carrier_id = "1587" + mcc='346' + mnc='140' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Cayman Islands:Lime:Modem' + carrier_id = "1587" + mcc='346' + mnc='140' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier='Cayman Islands:Mms' + carrier_id = "1587" + mcc='346' + mnc='140' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="348" + mnc="17" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="348" + mnc="17" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Bvi:Digicel:Internet' + carrier_id = "2356" + mcc='348' + mnc='77' + apn='wap.digicelbvi.com' + authtype='1' + type='default' + /> + + <apn carrier='Bvi:Digicel:Mms' + carrier_id = "2356" + mcc='348' + mnc='77' + apn='wap.digicelbvi.com' + authtype='1' + mmsc='http://mmc.digiceljamaica.com/servlets/mms' + mmsproxy='172.16.7.12' + mmsport='9201' + type='mms' + user='wapbvi' + password='wapbvi' + /> + + <apn carrier='Bvi:Digicel:Modem' + carrier_id = "2356" + mcc='348' + mnc='77' + apn='wap.digicelbvi.com' + port='8080' + authtype='1' + proxy='172.16.7.12' + mmsc='http://wapdigicel.com' + type='dun' + user='wapbvi' + password='wapbvi' + /> + + <apn carrier='Bvi:Lime:Internet' + carrier_id = "2289" + mcc='348' + mnc='170' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Bvi:Lime:Mms' + carrier_id = "2289" + mcc='348' + mnc='170' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Bvi:Lime:Modem' + carrier_id = "2289" + mcc='348' + mnc='170' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="352" + mnc="11" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="352" + mnc="11" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Grenada:Lime:Internet' + carrier_id = "2223" + mcc='352' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Grenada:Lime:Mms' + carrier_id = "2223" + mcc='352' + mnc='110' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Grenada:Lime:Modem' + carrier_id = "2223" + mcc='352' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="354" + mnc="86" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="354" + mnc="86" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Monserrat:Lime:Internet' + carrier_id = "2292" + mcc='354' + mnc='860' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Monserrat:Lime:Mms' + carrier_id = "2292" + mcc='354' + mnc='860' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Monserrat:Lime:Modem' + carrier_id = "2292" + mcc='354' + mnc='860' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="356" + mnc="11" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="356" + mnc="11" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='St Kitts And Nevis:Lime:Internet' + mcc='356' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='St Kitts And Nevis:Lime:Mms' + mcc='356' + mnc='110' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='St Kitts And Nevis:Lime:Modem' + mcc='356' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="358" + mnc="11" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="358" + mnc="11" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier="Lime Internet Postpaid" + mcc="360" + mnc="11" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier='St Lucia:Lime:Internet' + carrier_id = "2293" + mcc='358' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='St Lucia:Lime:Mms' + carrier_id = "2293" + mcc='358' + mnc='110' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='St Lucia:Lime:Modem' + carrier_id = "2293" + mcc='358' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Postpaid MMS" + mcc="360" + mnc="11" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='St Vincent:Lime:Internet' + carrier_id = "2294" + mcc='360' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='St Vincent:Lime:Mms' + carrier_id = "2294" + mcc='360' + mnc='110' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='St Vincent:Lime:Modem' + carrier_id = "2294" + mcc='360' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier='Curacao:Digicel:Internet' + carrier_id = "1332" + mcc='362' + mnc='69' + apn='web.digicelcuracao.com' + authtype='1' + type='default' + /> + + <apn carrier='Curacao:Digicel:Mms' + carrier_id = "1332" + mcc='362' + mnc='69' + apn='wap' + authtype='1' + mmsc='http://mms.digicelgroup.com' + mmsproxy='172.16.7.12' + mmsport='9201' + type='mms' + /> + + <apn carrier='Curacao:Digicel:Modem' + carrier_id = "1332" + mcc='362' + mnc='69' + apn='wap' + port='8080' + authtype='1' + proxy='172.16.7.12' + mmsc='http://wapdigicel.com' + type='dun' + /> + + <apn carrier="INTERNET Aruba" + carrier_id = "2163" + mcc="363" + mnc="02" + apn="web.digicelaruba.com" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Digicel" + carrier_id = "2163" + mcc="363" + mnc="02" + apn="wap" + user="" + password="" + mmsproxy="172.16.7.12" + mmsport="8080" + mmsc="http://mms.digicelgroup.com" + authtype="1" + type="mms" + /> + + <apn carrier="INTERNET Aruba" + carrier_id = "2163" + mcc="363" + mnc="020" + apn="web.digicelaruba.com" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Digicel" + carrier_id = "2163" + mcc="363" + mnc="020" + apn="wap" + user="" + password="" + mmsproxy="172.16.7.12" + mmsport="8080" + mmsc="http://mms.digicelgroup.com" + authtype="1" + type="mms" + /> + + <apn carrier="Be Aliv" + carrier_id = "2130" + mcc="364" + mnc="49" + apn="pda.newcomobile.com" + type="default,supl" + /> + + <apn carrier="Be Aliv IMS" + carrier_id = "2130" + mcc="364" + mnc="49" + apn="ims" + type="ims" + /> + + <apn carrier="Lime Internet Postpaid" + mcc="365" + mnc="84" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="365" + mnc="84" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Anguilla:Lime:Internet' + carrier_id = "2295" + mcc='365' + mnc='840' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Anguilla:Lime:Mms' + carrier_id = "2295" + mcc='365' + mnc='840' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Anguilla:Lime:Modem' + carrier_id = "2295" + mcc='365' + mnc='840' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Lime Internet Postpaid" + mcc="366" + mnc="11" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="366" + mnc="11" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Dominica:Lime:Internet' + carrier_id = "2290" + mcc='366' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='default' + /> + + <apn carrier='Dominica:Lime:Mms' + carrier_id = "2290" + mcc='366' + mnc='110' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Dominica:Lime:Modem' + carrier_id = "2290" + mcc='366' + mnc='110' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Internet" + carrier_id = "1444" + mcc="368" + mnc="01" + apn="internet" + type="default,supl" + /> + + + <apn carrier="Cubacel MMS" + carrier_id = "1444" + mcc="368" + mnc="01" + apn="mms" + mmsproxy="200.13.145.52" + mmsport="8080" + mmsc="http://mms.cubacel.cu" + type="mms" + /> + + <apn carrier="Orange Internet (LTE)" + carrier_id = "658" + mcc="370" + mnc="01" + apn="orangeinternet" + type="ia,default,supl" + /> + + <apn carrier="Orange net (3G)" + carrier_id = "658" + mcc="370" + mnc="01" + apn="orangenet.com.do" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "658" + mcc="370" + mnc="01" + apn="orangeworld" + user="orange" + password="orange" + mmsproxy="172.16.126.70" + mmsport="8080" + mmsc="http://mms.orange.com.do/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Internet Móvil Claro" + carrier_id = "1467" + mcc="370" + mnc="02" + apn="internet.ideasclaro.com.do" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1467" + mcc="370" + mnc="02" + apn="internet.ideasclaro.com.do" + mmsc="http://mms.ideasclaro.com.do/mms/wapenc" + type="mms" + /> + + <apn carrier="Internet Móvil Claro" + carrier_id = "1467" + mcc="370" + mnc="020" + apn="internet.ideasclaro.com.do" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1467" + mcc="370" + mnc="020" + apn="internet.ideasclaro.com.do" + mmsc="http://mms.ideasclaro.com.do/mms/wapenc" + type="mms" + /> + + <apn carrier="Viva Edge (GSM)" + carrier_id = "1469" + mcc="370" + mnc="04" + apn="edge.viva.net.do" + proxy="192.168.16.10" + port="9401" + user="viva" + password="viva" + authtype="1" + type="default,supl" + /> + + <apn carrier="Viva MMS" + carrier_id = "1469" + mcc="370" + mnc="04" + apn="mms.viva.net.do" + user="viva" + password="viva" + mmsproxy="192.168.16.10" + mmsport="9401" + mmsc="http://10.200.16.4/mms/wapenc" + authtype="1" + type="mms" + /> + + <apn carrier="Wind Telecom" + carrier_id = "2437" + mcc="370" + mnc="05" + apn="smart.wind4g.com.do" + type="default" + protocol="IPV4V6" + /> + + <apn carrier='Haiti:Digicel:Internet' + carrier_id = "1532" + mcc='372' + mnc='02' + apn='wap.digicelha.com' + authtype='1' + type='default' + /> + + <apn carrier='Haiti:Digicel:Mms' + carrier_id = "1532" + mcc='372' + mnc='02' + apn='wap.digicelha.com' + authtype='1' + mmsc='http://mmc.digicelhaiti.com/servlets/mms' + mmsproxy='172.20.200.12' + mmsport='9201' + type='mms' + user='wapha' + password='wap01ha' + /> + + <apn carrier='Haiti:Digicel:Modem' + carrier_id = "1532" + mcc='372' + mnc='02' + apn='wap.digicelha.com' + port='8080' + authtype='1' + proxy='172.20.200.12' + mmsc='http://wapdigicel.com' + type='dun' + user='wapha' + password='wap01ha' + /> + + <apn carrier='NATCOM INTERNET' + carrier_id = "1533" + mcc="372" + mnc="03" + apn="natcom" + type="default,supl" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="12" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="12" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + mcc="374" + mnc="120" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + mcc="374" + mnc="120" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + mcc="374" + mnc="121" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + mcc="374" + mnc="121" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="122" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="122" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="123" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="123" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="124" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="124" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="125" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="125" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="126" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="126" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="127" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="127" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="128" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="128" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="Bmobile internet" + carrier_id = "1739" + mcc="374" + mnc="129" + apn="internet" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="Bmobile mms" + carrier_id = "1739" + mcc="374" + mnc="129" + apn="mms" + user="" + password="" + mmsproxy="192.168.210.104" + mmsport="8080" + mmsc="http://192.168.210.104/mmrelay.app" + authtype="1" + type="mms" + /> + + <apn carrier="INTERNET Trinidad" + carrier_id = "1740" + mcc="374" + mnc="13" + apn="web.digiceltt.com" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Trinidad" + carrier_id = "1740" + mcc="374" + mnc="13" + apn="wap.digiceltt.com" + user="wap" + password="wap" + mmsproxy="172.20.6.12" + mmsport="8080" + mmsc="http://mmc.digiceltt.com/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="INTERNET Trinidad" + carrier_id = "1740" + mcc="374" + mnc="130" + apn="web.digiceltt.com" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Trinidad" + carrier_id = "1740" + mcc="374" + mnc="130" + apn="wap.digiceltt.com" + user="wap" + password="wap" + mmsproxy="172.20.6.12" + mmsport="8080" + mmsc="http://mmc.digiceltt.com/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Lime Internet Postpaid" + mcc="376" + mnc="35" + apn="internet" + user="" + password="" + type="default,supl" + /> + + <apn carrier="Lime Postpaid MMS" + mcc="376" + mnc="35" + apn="multimedia" + user="" + password="" + mmsproxy="10.20.5.34" + mmsport="8799" + mmsc="http://mmsc" + type="mms" + /> + + <apn carrier='Turks And Caicos:Lime:Internet' + carrier_id = "2291" + mcc='376' + mnc='350' + apn='internet' + authtype='1' + type='default' + /> + + <apn carrier='Turks And Caicos:Lime:Mms' + carrier_id = "2291" + mcc='376' + mnc='350' + apn='multimedia' + authtype='1' + mmsc='http://mmsc' + mmsproxy='10.20.5.34' + mmsport='8799' + type='mms' + /> + + <apn carrier='Turks And Caicos:Lime:Modem' + carrier_id = "2291" + mcc='376' + mnc='350' + apn='internet' + authtype='1' + mmsc='http://www.time4lime.com/' + type='dun' + /> + + <apn carrier="Azercell" + carrier_id = "1354" + mcc="400" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Bakcell" + carrier_id = "495" + mcc="400" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="FONEX" + carrier_id = "1355" + mcc="400" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Nar Mobile" + carrier_id = "1356" + mcc="400" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Beeline Internet" + carrier_id = "1588" + mcc="401" + mnc="01" + apn="internet.beeline.kz" + user="@internet.beeline" + password="beeline" + authtype="1" + type="default,supl" + /> + + <apn carrier="Beeline MMS" + carrier_id = "1588" + mcc="401" + mnc="01" + apn="mms.beeline.kz" + user="@mms.beeline" + password="beeline" + authtype="1" + mmsc="http://mms.beeline.kz/mms/wapenc" + mmsproxy="172.27.6.93" + mmsport="8080" + type="mms" + /> + + <apn carrier="DOS Internet" + carrier_id = "1588" + mcc="401" + mnc="01" + apn="internet.dos.kz" + type="default,supl" + /> + + <apn carrier="izi" + carrier_id = "2436" + mcc="401" + mnc="01" + apn="izi.me" + type="default,supl" + mvno_type="imsi" + mvno_match_data="40101568" + /> + + <apn carrier="Kcell Internet" + carrier_id = "1589" + mcc="401" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Kcell MMS" + carrier_id = "1589" + mcc="401" + mnc="02" + apn="mms" + mmsc="http://mms.kcell.kz/post" + mmsproxy="195.47.255.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="ALTEL INTERNET" + carrier_id = "2164" + mcc="401" + mnc="07" + apn="internet" + type="default,supl" + /> + + <apn carrier="Tele2 Internet" + carrier_id = "1986" + mcc="401" + mnc="77" + apn="internet" + type="default,supl" + /> + + <apn carrier="Tele2 MMS" + carrier_id = "1986" + mcc="401" + mnc="77" + apn="mms" + mmsc="http://mms.tele2.kz/mms/wapenc" + mmsproxy="10.1.26.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="B-Mobile" + carrier_id = "564" + mcc="402" + mnc="11" + apn="default" + type="default,supl" + protocol="IPV4V6" + /> + + <apn carrier="TashiCell" + carrier_id = "2165" + mcc="402" + mnc="77" + apn="ticlnet" + user="" + password="" + proxy="" + port="" + type="default,supl" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="01" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="01" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="01" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="02" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="02" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="02" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="03" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="03" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="03" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="04" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="04" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="04" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="05" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="05" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="05" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="07" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="07" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="07" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="09" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="09" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="09" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Mobile Office" + mcc="404" + mnc="10" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + mcc="404" + mnc="10" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + mcc="404" + mnc="10" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="11" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="11" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="11" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="12" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="12" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="12" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="13" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="13" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="13" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="14" + apn="mmsc" + mmsc="http://10.11.12.180" + mmsproxy="10.11.12.13" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="14" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="14" + apn="imis" + proxy="10.11.12.13" + port="8080" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="15" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="15" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="15" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="16" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="16" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="16" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="17" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="17" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="17" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="17" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40417)" + mcc="404" + mnc="17" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="17" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="18" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="18" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="18" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Reliance Internet (40418)" + carrier_id = "1543" + mcc="404" + mnc="18" + apn="rcomnet" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="19" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="19" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="19" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="20" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="20" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="20" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Loop Mobile MMS" + carrier_id = "1545" + mcc="404" + mnc="21" + apn="mizone" + password="mmsc" + mmsc="http://mms.loopmobile.in:8080" + mmsproxy="10.0.0.10" + mmsport="9401" + type="mms" + /> + + <apn carrier="Loop Mobile" + carrier_id = "1545" + mcc="404" + mnc="21" + apn="www" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="22" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="22" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="22" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="24" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="24" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="24" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="25" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="25" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="25" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="25" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40425)" + mcc="404" + mnc="25" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="25" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="27" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="27" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="27" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="28" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="28" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="28" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="28" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40428)" + mcc="404" + mnc="28" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="28" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="29" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="29" + apn="myaircelpost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="29" + apn="myaircel" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="29" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40429)" + mcc="404" + mnc="29" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel WAP (40429)" + mcc="404" + mnc="29" + apn="aircelwap" + type="default,supl" + proxy="172.17.83.69" + port="8080" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="29" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="30" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="30" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="30" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="31" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="31" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="31" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="33" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="33" + apn="myaircelpost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="33" + apn="myaircel" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="33" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40433)" + mcc="404" + mnc="33" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel WAP (40433)" + mcc="404" + mnc="33" + apn="aircelwap" + type="default,supl" + proxy="172.17.83.69" + port="8080" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="33" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="34" + apn="bsnlnet" + authtype="1" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="34" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="34" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="35" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="35" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="35" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="35" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40435)" + mcc="404" + mnc="35" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="35" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="36" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="36" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="36" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Reliance Internet (40436)" + carrier_id = "1543" + mcc="404" + mnc="36" + apn="rcomnet" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="37" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="37" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="37" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="37" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40437)" + mcc="404" + mnc="37" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="37" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="38" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="38" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="38" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="40" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="40" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="40" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelgprs.po" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelgprs.pr" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelwap.po" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelwap.pr" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40441)" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel WAP (40441)" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelwap" + type="default,supl" + proxy="172.17.83.69" + port="8080" + /> + + <apn carrier="Aircel-MMS-Postpaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelmms.po" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel-MMS-Prepaid" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelmms.pr" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel MMS (40441)" + carrier_id = "1550" + mcc="404" + mnc="41" + apn="aircelmms" + mmsproxy="172.17.83.69" + mmsport="8080" + mmsc="http://172.17.83.67/servlets/mms" + type="mms" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelgprs.po" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelgprs.pr" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelwap.po" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelwap.pr" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Aircel Internet (40442)" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelgprs" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Aircel-MMS-Postpaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelmms.po" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel-MMS-Prepaid" + carrier_id = "1551" + mcc="404" + mnc="42" + apn="aircelmms.pr" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="43" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="43" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="43" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="44" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="44" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="44" + apn="mmsc" + mmsc="http://10.4.42.21:8002" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="45" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="45" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="45" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="46" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="46" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="46" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="49" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="49" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="49" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="50" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="50" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="50" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="51" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="51" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="51" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="52" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="52" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="52" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="53" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="53" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="53" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="54" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="54" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="54" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="55" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="55" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="55" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="56" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="56" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="56" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="57" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="57" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="57" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="58" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="58" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="58" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="59" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="59" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="59" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="60" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="60" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="60" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="62" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="62" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="62" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="64" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="64" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="64" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="66" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="66" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="66" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="67" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="67" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="67" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTNL" + carrier_id = "1556" + mcc="404" + mnc="68" + apn="mtnl.net" + authtype="0" + user="mtnl" + password="mtnl123" + mmsc="http://mtnlmms/" + mmsproxy="10.10.10.10" + mmsport="9401" + type="default,mms,supl,agps,fota,dun" + /> + + <apn carrier="MTNL" + carrier_id = "1556" + mcc="404" + mnc="69" + apn="mtnl.net" + authtype="0" + user="mtnl" + password="mtnl123" + mmsc="http://mtnlmms/" + mmsproxy="10.10.10.10" + mmsport="9401" + type="default,mms,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Mobile Office" + carrier_id = "1557" + mcc="404" + mnc="70" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1557" + mcc="404" + mnc="70" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1557" + mcc="404" + mnc="70" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="71" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="71" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="71" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="72" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="72" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="72" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="73" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="73" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="73" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="74" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="74" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="74" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="75" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="75" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="75" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="76" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="76" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="76" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="77" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="77" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="77" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="78" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="78" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="78" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="79" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="79" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="79" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="80" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="80" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="80" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="bsnlmms" + carrier_id = "1549" + mcc="404" + mnc="81" + apn="bsnlmms" + mmsc="http://bsnlmmsc.in:8514" + mmsproxy="10.210.10.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="bsnlnet" + carrier_id = "1549" + mcc="404" + mnc="81" + apn="bsnlnet" + type="default,supl" + /> + + <apn carrier="bsnllive" + carrier_id = "1549" + mcc="404" + mnc="81" + apn="bsnllive" + proxy="10.220.67.131" + port="8080" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="82" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="82" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="82" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1559" + mcc="404" + mnc="83" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1559" + mcc="404" + mnc="83" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1559" + mcc="404" + mnc="83" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="84" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="84" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="84" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="404" + mnc="85" + apn="mms" + mmsc="http://10.239.221.47/mms/" + mmsproxy="10.239.221.7" + mmsport="8080" + type="mms" + /> + + <apn carrier="Reliance Net" + carrier_id = "1543" + mcc="404" + mnc="85" + apn="smartnet" + type="default,supl" + /> + + <apn carrier="Reliance WAP" + carrier_id = "1543" + mcc="404" + mnc="85" + apn="smartwap" + proxy="10.239.221.7" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="86" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="86" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="86" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="87" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="87" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="87" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="404" + mnc="88" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="404" + mnc="88" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="404" + mnc="88" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="404" + mnc="89" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="404" + mnc="89" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="404" + mnc="89" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="90" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="90" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="90" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Aircel-GPRS-Postpaid" + mcc="404" + mnc="91" + apn="aircelwebpost" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Postpaid" + mcc="404" + mnc="91" + apn="aircelwappost" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Pocket Internet-Prepaid" + mcc="404" + mnc="91" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-GPRS-Prepaid" + mcc="404" + mnc="91" + apn="aircelweb" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="404" + mnc="91" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="92" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="92" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="92" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="93" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="93" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="93" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="94" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="94" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="94" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="95" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="95" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="95" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="96" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="96" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="96" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="97" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="97" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="97" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="404" + mnc="98" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="404" + mnc="98" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="404" + mnc="98" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="01" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="01" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="01" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="03" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="03" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="03" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="04" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="04" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="04" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="05" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="05" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="05" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="06" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="06" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="06" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="07" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="07" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="07" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="08" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="08" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="08" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="09" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="09" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="09" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="10" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="10" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="10" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="11" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="11" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="11" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="12" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="12" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="12" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="13" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="13" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="13" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="14" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="14" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="14" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="15" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="15" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="15" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="17" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="17" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="17" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="18" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="18" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="18" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="19" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="19" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="19" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="20" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="20" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="20" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="21" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="21" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="21" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="22" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="22" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="22" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="Reliance MMS" + carrier_id = "1543" + mcc="405" + mnc="23" + apn="rcommms" + mmsc="http://mmsc.rcom.co.in/mms/" + mmsproxy="10.239.221.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="Netconnect" + carrier_id = "1543" + mcc="405" + mnc="23" + apn="rcomnet" + type="default,supl" + /> + + <apn carrier="RelianceMbWorld" + carrier_id = "1543" + mcc="405" + mnc="23" + apn="rcomwap" + proxy="10.239.221.5" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="025" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="025" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="025" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="026" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="026" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="026" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="027" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="027" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="027" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="028" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="028" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="028" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="029" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="029" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="029" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="030" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="030" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="030" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="031" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="031" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="031" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="032" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="032" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="032" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="033" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="033" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="033" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="034" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="034" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="034" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="035" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="035" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="035" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="036" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="036" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="036" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="037" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="037" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="037" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="038" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="038" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="038" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="039" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="039" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="039" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="040" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="040" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="040" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="041" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="041" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="041" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="042" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="042" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="042" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="043" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="043" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="043" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="044" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="044" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="044" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="045" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="045" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="045" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="046" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="046" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="046" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="TATA DOCOMO INTERNET" + carrier_id = "1982" + mcc="405" + mnc="047" + apn="TATA.DOCOMO.INTERNET" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO DIVE-IN" + carrier_id = "1982" + mcc="405" + mnc="047" + apn="TATA.DOCOMO.DIVE.IN" + proxy="10.124.94.7" + port="8080" + type="default,supl" + /> + + <apn carrier="TATA DOCOMO MMS" + carrier_id = "1982" + mcc="405" + mnc="047" + apn="TATA.DOCOMO.MMS" + mmsc="http://mmsc/" + mmsproxy="10.124.26.94" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="51" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="51" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="51" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="52" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="52" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="52" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="53" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="53" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="53" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="54" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="54" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="54" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="55" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="55" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="55" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Mobile Office" + carrier_id = "1961" + mcc="405" + mnc="56" + apn="airtelgprs.com" + type="default,supl" + /> + + <apn carrier="AIRTEL LIVE" + carrier_id = "1961" + mcc="405" + mnc="56" + apn="airtelfun.com" + proxy="100.1.200.99" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1961" + mcc="405" + mnc="56" + apn="airtelmms.com" + authtype="1" + mmsc="http://100.1.201.171:10021/mmsc" + mmsproxy="100.1.201.172" + mmsport="8799" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="66" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="66" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="66" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="67" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="67" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="67" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="70" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="70" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="70" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="750" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="750" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="750" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="751" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="751" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="751" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="752" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="752" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="752" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="753" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="753" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="753" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="754" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="754" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="754" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="755" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="755" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="755" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Vodafone_MMS" + carrier_id = "2378" + mcc="405" + mnc="756" + apn="portalnmms" + mmsc="http://mms1.live.vodafone.in/mms/" + mmsproxy="10.10.1.100" + mmsport="9401" + type="mms" + /> + + <apn carrier="Vodafonemobileconnect" + carrier_id = "2378" + mcc="405" + mnc="756" + apn="www" + type="default,supl" + /> + + <apn carrier="Vodafone live" + carrier_id = "2378" + mcc="405" + mnc="756" + apn="portalnmms" + proxy="10.10.1.100" + port="9401" + type="default,supl" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="799" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="799" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="799" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="800" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="800" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="800" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="801" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="801" + apn="aircelwap" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="801" + apn="aircelmms" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="802" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="802" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="802" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="803" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="803" + apn="aircelwap" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="803" + apn="aircelmms" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="804" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="804" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="804" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="805" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="805" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="805" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="806" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="806" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="806" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="807" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="807" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="807" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="808" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="808" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="808" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="809" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="809" + apn="aircelwap" + proxy="192.168.35.201" + port="8081" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="809" + apn="aircelmms" + mmsc="http://mmsc/mmrelay.app" + mmsproxy="192.168.35.196" + mmsport="8081" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="810" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="810" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="810" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="811" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="811" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="811" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Aircel-GPRS" + mcc="405" + mnc="812" + apn="aircelgprs" + type="default,supl" + /> + + <apn carrier="Pocket Internet" + mcc="405" + mnc="812" + apn="aircelwap" + proxy="172.17.83.69" + port="8080" + type="default,supl" + /> + + <apn carrier="Aircel-MMS" + mcc="405" + mnc="812" + apn="aircelmms" + mmsc="http://10.50.1.166/servlets/mms" + mmsproxy="172.17.83.69" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="813" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="813" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="813" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="814" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="814" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="814" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="815" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="815" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="815" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="816" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="816" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="816" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="817" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="817" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="817" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="818" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="818" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="818" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="819" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="819" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="819" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="820" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="820" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="820" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="821" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="821" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="821" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="822" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="822" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="822" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="823" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="823" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="824" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="824" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="825" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="825" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="826" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="826" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="827" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="827" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="828" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="828" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="829" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="829" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="830" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="830" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + mcc="405" + mnc="831" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + mcc="405" + mnc="831" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="832" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="832" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="833" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="833" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="834" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="834" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="835" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="835" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="836" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="836" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="837" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="837" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="838" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="838" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + mcc="405" + mnc="839" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + mcc="405" + mnc="839" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2018" + mcc="405" + mnc="840" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2018" + mcc="405" + mnc="840" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="841" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="841" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="842" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="842" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="843" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="843" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="844" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="844" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="844" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="845" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="845" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="845" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="846" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="846" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="846" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="847" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="847" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="847" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="848" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="848" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="848" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="849" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="849" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="849" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="850" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="850" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="850" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="851" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="851" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="851" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="852" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="852" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="852" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Idea_Internet" + carrier_id = "802" + mcc="405" + mnc="853" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA GPRS" + carrier_id = "802" + mcc="405" + mnc="853" + apn="imis" + proxy="10.4.42.15" + port="8080" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="853" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Loop Internet (405854)" + carrier_id = "2018" + mcc="405" + mnc="854" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405854)" + carrier_id = "2018" + mcc="405" + mnc="854" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405855)" + carrier_id = "2018" + mcc="405" + mnc="855" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405855)" + carrier_id = "2018" + mcc="405" + mnc="855" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405856)" + carrier_id = "2018" + mcc="405" + mnc="856" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405856)" + carrier_id = "2018" + mcc="405" + mnc="856" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405857)" + carrier_id = "2018" + mcc="405" + mnc="857" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405857)" + carrier_id = "2018" + mcc="405" + mnc="857" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405858)" + carrier_id = "2018" + mcc="405" + mnc="858" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405858)" + carrier_id = "2018" + mcc="405" + mnc="858" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405859)" + carrier_id = "2018" + mcc="405" + mnc="859" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405859)" + carrier_id = "2018" + mcc="405" + mnc="859" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405860)" + carrier_id = "2018" + mcc="405" + mnc="860" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405860)" + carrier_id = "2018" + mcc="405" + mnc="860" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405861)" + carrier_id = "2018" + mcc="405" + mnc="861" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405861)" + carrier_id = "2018" + mcc="405" + mnc="861" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405862)" + carrier_id = "2018" + mcc="405" + mnc="862" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405862)" + carrier_id = "2018" + mcc="405" + mnc="862" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405863)" + carrier_id = "2018" + mcc="405" + mnc="863" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405863)" + carrier_id = "2018" + mcc="405" + mnc="863" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405864)" + carrier_id = "2018" + mcc="405" + mnc="864" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405864)" + carrier_id = "2018" + mcc="405" + mnc="864" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405865)" + carrier_id = "2018" + mcc="405" + mnc="865" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405865)" + carrier_id = "2018" + mcc="405" + mnc="865" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405866)" + carrier_id = "2018" + mcc="405" + mnc="866" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405866)" + carrier_id = "2018" + mcc="405" + mnc="866" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405867)" + carrier_id = "2018" + mcc="405" + mnc="867" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405867)" + carrier_id = "2018" + mcc="405" + mnc="867" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405868)" + carrier_id = "2018" + mcc="405" + mnc="868" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405868)" + carrier_id = "2018" + mcc="405" + mnc="868" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405869)" + carrier_id = "2018" + mcc="405" + mnc="869" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405869)" + carrier_id = "2018" + mcc="405" + mnc="869" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405870)" + carrier_id = "2018" + mcc="405" + mnc="870" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405870)" + carrier_id = "2018" + mcc="405" + mnc="870" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405871)" + carrier_id = "2018" + mcc="405" + mnc="871" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405871)" + carrier_id = "2018" + mcc="405" + mnc="871" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405872)" + carrier_id = "2018" + mcc="405" + mnc="872" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405872)" + carrier_id = "2018" + mcc="405" + mnc="872" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405873)" + carrier_id = "2018" + mcc="405" + mnc="873" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405873)" + carrier_id = "2018" + mcc="405" + mnc="873" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop Internet (405874)" + carrier_id = "2018" + mcc="405" + mnc="874" + apn="www" + type="default,supl,agps,fota,dun" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Loop MMS (405874)" + carrier_id = "2018" + mcc="405" + mnc="874" + apn="mizone" + mmsproxy="10.0.0.10" + mmsport="9401" + mmsc="http://mms.loopmobile.in:8080/" + type="mms" + protocol="IP" + roaming_protocol="IP" + carrier_enabled="true" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="875" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="875" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="875" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="876" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="876" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="876" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="877" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="877" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="877" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="878" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="878" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="878" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="879" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="879" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="879" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="880" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="880" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="880" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="881" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="882" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="883" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="884" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="885" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="STEL" + carrier_id = "2265" + mcc="405" + mnc="886" + apn="gprs.stel.in" + type="default,supl" + /> + + <apn carrier="IDEA" + carrier_id = "802" + mcc="405" + mnc="908" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="908" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="IDEA" + carrier_id = "802" + mcc="405" + mnc="909" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="909" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="IDEA" + carrier_id = "802" + mcc="405" + mnc="910" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="910" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="IDEA" + carrier_id = "802" + mcc="405" + mnc="911" + apn="internet" + type="default,supl" + /> + + <apn carrier="IDEA MMS" + carrier_id = "802" + mcc="405" + mnc="911" + apn="mmsc" + mmsc="http://10.4.42.21:8002/" + mmsproxy="10.4.42.15" + mmsport="8080" + type="mms" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="912" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="913" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="914" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="915" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="916" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="917" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="918" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="919" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="920" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="921" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="922" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="923" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + mcc="405" + mnc="924" + apn="internet" + type="default,supl" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="925" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="925" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="925" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="926" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="926" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="926" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="927" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="927" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="927" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="928" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="928" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="928" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Uninor Internet" + carrier_id = "2002" + mcc="405" + mnc="929" + apn="uninor" + authtype="1" + type="default,supl" + /> + + <apn carrier="Uninor Wap" + carrier_id = "2002" + mcc="405" + mnc="929" + apn="uninor" + proxy="10.58.10.58" + port="8080" + type="default,supl" + /> + + <apn carrier="Uninor MMS" + carrier_id = "2002" + mcc="405" + mnc="929" + apn="uninor" + mmsc="http://10.58.2.120" + mmsproxy="10.58.10.59" + mmsport="8080" + type="mms" + /> + + <apn carrier="Cheers" + carrier_id = "2266" + mcc="405" + mnc="930" + apn="internet" + type="default,supl" + /> + + <apn carrier="Cheers" + mcc="405" + mnc="931" + apn="internet" + type="default,supl" + /> + + <apn carrier="Videocon MMS" + carrier_id = "2264" + mcc="405" + mnc="932" + apn="vgprs.com" + mmsc="http://10.202.4.119:10021/mmsc/" + mmsproxy="10.202.5.145" + mmsport="8799" + type="mms" + /> + + <apn carrier="Videocon" + carrier_id = "2264" + mcc="405" + mnc="932" + apn="vinternet.com" + type="default,supl" + /> + + <apn carrier="Mobilink WAP GPRS" + carrier_id = "1656" + mcc="410" + mnc="01" + apn="connect.mobilinkworld.com" + user="Mobilink" + password="Mobilink" + type="default,supl" + /> + + <apn carrier="Mobilink MMS" + carrier_id = "1656" + mcc="410" + mnc="01" + apn="mms.mobilinkworld.com" + user="Mobilink" + password="Mobilink" + mmsc="http://mms/" + mmsproxy="172.25.20.12" + mmsport="8080" + type="mms" + /> + + <apn carrier="Ufone WAP" + carrier_id = "1657" + mcc="410" + mnc="03" + apn="Ufone.internet" + type="default,supl" + /> + + <apn carrier="Ufone MMS" + carrier_id = "1657" + mcc="410" + mnc="03" + apn="Ufone.mms" + mmsc="http://www.ufonemms.com:80/" + mmsproxy="172.16.13.27" + mmsport="8080" + type="mms" + /> + + <apn carrier="ZONG WAP" + carrier_id = "1980" + mcc="410" + mnc="04" + apn="zonginternet" + type="default,supl" + /> + + <apn carrier="ZONG MMS" + carrier_id = "1980" + mcc="410" + mnc="04" + apn="zongmms" + mmsc="http://10.81.6.11:8080" + mmsproxy="10.81.6.33" + mmsport="8000" + type="mms" + /> + + <apn carrier="Telenor WAP" + carrier_id = "1975" + mcc="410" + mnc="06" + apn="internet" + type="default,supl" + /> + + <apn carrier="Telenor MMS" + carrier_id = "1975" + mcc="410" + mnc="06" + apn="mms" + user="Telenor" + password="Telenor" + mmsc="http://mmstelenor" + mmsproxy="172.18.19.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="Warid WAP" + carrier_id = "1656" + mcc="410" + mnc="07" + apn="Wap.warid" + type="default,supl" + /> + + <apn carrier="Warid MMS" + carrier_id = "1656" + mcc="410" + mnc="07" + apn="mms.warid" + mmsc="http://10.4.0.132/servlets/MMS" + mmsproxy="10.4.2.1" + mmsport="8080" + type="mms" + /> + + <apn carrier='Consumer Cellular' + mcc='410' + mnc='310' + apn='att.mvno' + type='default,mms,supl,hipri,fota' + protocol='IP' + roaming_protocol='IP' + mmsc='http://mms.fido.ca' + mmsproxy='mmsproxy.fido.ca' + mmsport='80' + mvno_type='gid' + mvno_match_data='2AC9' + /> + + <apn carrier="AWCC" + carrier_id = "452" + mcc="412" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Roshan" + carrier_id = "453" + mcc="412" + mnc="20" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "455" + mcc="412" + mnc="40" + apn="default" + type="default,supl" + /> + + <apn carrier="Etisalat" + carrier_id = "2221" + mcc="412" + mnc="50" + apn="default" + type="default,supl" + /> + + <apn carrier="Mobitel" + carrier_id = "1931" + mcc="413" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Dialog" + carrier_id = "1599" + mcc="413" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Etisalat" + carrier_id = "1600" + mcc="413" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1932" + mcc="413" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Hutch" + carrier_id = "1933" + mcc="413" + mnc="08" + apn="default" + type="default,supl" + /> + + <apn carrier="MPT" + carrier_id = "1611" + mcc="414" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Ooredoo Internet" + carrier_id = "1996" + mcc="414" + mnc="05" + apn="Internet" + type="default,supl" + /> + + <apn carrier="Alfa Internet" + carrier_id = "1920" + mcc="415" + mnc="01" + user="mic1" + password="mic1" + apn="internet.mic1.com.lb" + type="default,supl" + /> + + <apn carrier="Alfawap" + carrier_id = "1920" + mcc="415" + mnc="01" + apn="wap.mic1.com.lb" + user="mic1" + password="mic1" + proxy="192.168.23.50" + port="80" + type="default,supl" + /> + + <apn carrier="Alfa MMS" + carrier_id = "1920" + mcc="415" + mnc="01" + user="mic1" + password="mic1" + apn="mms.mic1.com.lb" + mmsc="http://mms.mic1.com.lb" + mmsproxy="192.168.23.51" + mmsport="8080" + type="mms" + /> + + <apn carrier="touch" + carrier_id = "1921" + mcc="415" + mnc="03" + apn="touch" + type="default,supl" + /> + + <apn carrier="touch_WAP" + carrier_id = "1921" + mcc="415" + mnc="03" + apn="wap" + proxy="192.168.4.11" + port="80" + type="default,supl" + /> + + <apn carrier="touch_MMS" + carrier_id = "1921" + mcc="415" + mnc="03" + user="touch" + apn="mms" + mmsc="http://mms:8088/mms/" + mmsproxy="192.168.4.103" + mmsport="80" + type="mms" + /> + + <apn carrier="Zain JO Internet" + carrier_id = "1578" + mcc="416" + mnc="01" + apn="zain" + user="zain" + password="zain" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Zain JO WAP" + carrier_id = "1578" + mcc="416" + mnc="01" + apn="zain" + user="zain" + password="zain" + authtype="1" + proxy="192.168.55.10" + port="80" + type="default,supl" + /> + + + <apn carrier="Zain JO Streaming" + carrier_id = "1578" + mcc="416" + mnc="01" + apn="Zain" + user="zain" + password="zain" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Zain JO MMS" + carrier_id = "1578" + mcc="416" + mnc="01" + apn="zain" + user="zain" + password="zain" + authtype="1" + mmsc="http://mms.jo.zain.com" + mmsproxy="192.168.55.10" + mmsport="80" + type="mms" + /> + + + <apn carrier="Umniah internet" + carrier_id = "1580" + mcc="416" + mnc="03" + apn="net" + type="default,supl" + /> + + <apn carrier="Umniah WAP" + carrier_id = "1580" + mcc="416" + mnc="03" + apn="wap" + proxy="10.1.1.10" + port="8080" + type="default,supl" + /> + + + <apn carrier="Umniah MMS" + carrier_id = "1580" + mcc="416" + mnc="03" + apn="mms" + mmsc="http://mms.umniah.com/" + mmsproxy="10.1.1.10" + mmsport="8080" + type="mms" + /> + + + <apn carrier="Orange MMS" + carrier_id = "849" + mcc="416" + mnc="770" + apn="mms.orange.jo" + user="mmc" + password="mmc" + authtype="1" + mmsc="http://172.16.1.96/servlets/mms" + mmsproxy="172.16.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "849" + mcc="416" + mnc="770" + apn="net.orange.jo" + user="net" + password="net" + authtype="1" + type="default,supl" + /> + + <apn carrier="Orange WAP" + carrier_id = "849" + mcc="416" + mnc="770" + apn="wap.orange.jo" + user="wap" + password="wap" + authtype="1" + proxy="172.16.1.2" + port="8080" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "849" + mcc="416" + mnc="77" + apn="mms.orange.jo" + user="mmc" + password="mmc" + authtype="1" + mmsc="http://172.16.1.96/servlets/mms" + mmsproxy="172.16.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "849" + mcc="416" + mnc="77" + apn="net.orange.jo" + user="net" + password="net" + authtype="1" + type="default,supl" + /> + + <apn carrier="Orange WAP" + carrier_id = "849" + mcc="416" + mnc="77" + apn="wap.orange.jo" + user="wap" + password="wap" + authtype="1" + proxy="172.16.1.2" + port="8080" + type="default,supl" + /> + + + <apn carrier="Syriatel Net" + carrier_id = "1088" + mcc="417" + mnc="01" + apn="net.syriatel.com" + type="default,supl" + /> + + <apn carrier="Syriatel MMS" + carrier_id = "1088" + mcc="417" + mnc="01" + apn="mms.syriatel.com" + mmsc="http://mymms.syriatel.com/" + mmsproxy="172.20.5.6" + mmsport="80" + type="mms" + /> + + <apn carrier="MTN WAP" + carrier_id = "1089" + mcc="417" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="MTN MMS" + carrier_id = "1089" + mcc="417" + mnc="02" + apn="mms" + mmsc="http://mms/" + mmsproxy="10.110.0.134" + mmsport="8799" + type="mms" + /> + + <apn carrier="Asiacell Internet" + carrier_id = "1969" + mcc="418" + mnc="05" + apn="net.asiacell.com" + type="default" + /> + + <apn carrier="MMS" + carrier_id = "1969" + mcc="418" + mnc="05" + apn="wap.asiacell.com" + mmsc="http://mvas.asiacell.com/uportal" + mmsproxy="192.168.107.50" + mmsport="8080" + type="mms" + /> + + <apn carrier="SanaTel" + carrier_id = "2166" + mcc="418" + mnc="08" + apn="default" + type="default,supl" + /> + + <apn carrier="ZAIN-GPRS" + carrier_id = "1971" + mcc="418" + mnc="20" + apn="internet" + user="atheer" + password="atheer" + authtype="1" + type="default,supl" + /> + + <apn carrier="Zain-MMS" + carrier_id = "1971" + mcc="418" + mnc="20" + apn="MMS" + user="atheer" + password="atheer" + authtype="1" + mmsc="http://mms:8002/" + mmsproxy="172.29.11.12" + mmsport="8080" + type="mms" + /> + + <apn carrier="ZAIN-GPRS" + carrier_id = "1971" + mcc="418" + mnc="30" + apn="internet" + user="atheer" + password="atheer" + authtype="1" + type="default,supl" + /> + + <apn carrier="Zain-MMS" + carrier_id = "1971" + mcc="418" + mnc="30" + apn="MMS" + user="atheer" + password="atheer" + authtype="1" + mmsc="http://mms:8002/" + mmsproxy="172.29.11.12" + mmsport="8080" + type="mms" + /> + + <apn carrier="Korek 9595" + carrier_id = "1983" + mcc="418" + mnc="40" + apn="internet.korek.com" + type="default,supl" + /> + + <apn carrier="Korek 9191" + carrier_id = "1983" + mcc="418" + mnc="40" + apn="net.korek.com" + user="korek" + password="korek" + type="default,supl" + /> + + <apn carrier="Korek 9494" + carrier_id = "1983" + mcc="418" + mnc="40" + apn="internet.korek.com" + type="default,supl" + /> + + <apn carrier="KOREK MMS" + carrier_id = "1983" + mcc="418" + mnc="40" + apn="mms.korek.com" + user="korek" + password="korek" + authtype="1" + mmsc="http://mms.korektel.com/mms/wapenc" + mmsproxy="192.168.18.187" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobitel" + carrier_id = "2345" + mcc="418" + mnc="45" + apn="default" + type="default,supl" + /> + + <apn carrier="Itisaluna" + carrier_id = "2234" + mcc="418" + mnc="62" + apn="default" + type="default,supl" + /> + + <apn carrier="Omnnea" + carrier_id = "2167" + mcc="418" + mnc="92" + apn="default" + type="default,supl" + /> + + <apn carrier="MI" + carrier_id = "1585" + mcc="419" + mnc="02" + apn="pps" + user="pps" + password="pps" + type="default,supl" + /> + + <apn carrier="Zain WAP" + carrier_id = "1585" + mcc="419" + mnc="02" + apn="pps" + user="pps" + password="pps" + authtype="3" + proxy="10.43.4.5" + port="8080" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1585" + mcc="419" + mnc="02" + apn="pps" + user="mms" + password="mms" + authtype="3" + mmsc="http://mms.zain" + mmsproxy="176.0.0.65" + mmsport="8080" + type="mms" + /> + + <apn carrier="Ooredoo Action" + carrier_id = "1586" + mcc="419" + mnc="03" + apn="action.ooredoo.com" + authtype="1" + type="default" + /> + + <apn carrier="Ooredoo MMS" + carrier_id = "1586" + mcc="419" + mnc="03" + apn="mms.ooredoo.com" + mmsc="http://action.ooredoo.com" + mmsproxy="194.126.53.64" + mmsport="8080" + authtype="1" + type="default" + /> + + <apn carrier="VIVA - KW" + carrier_id = "1992" + mcc="419" + mnc="04" + apn="viva" + authtype="0" + mmsc="http://172.16.128.80:38090/was" + mmsproxy="172.16.128.228" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="STC - GPRS" + carrier_id = "1683" + mcc="420" + mnc="01" + apn="jawalnet.com.sa" + type="default,supl" + /> + + <apn carrier="STC MMS" + carrier_id = "1683" + mcc="420" + mnc="01" + apn="mms.net.sa" + mmsc="http://mms.net.sa:8002/" + mmsproxy="10.1.1.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobily WEB" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="web1" + type="default,supl" + /> + + <apn carrier="Mobily prepaid - GPRS" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="wap2" + proxy="10.3.2.133" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobily postpaid - GPRS" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="wap1" + proxy="10.3.2.133" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobily WEB 2" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="web2" + type="default,supl" + /> + + <apn carrier="Mobily MMS Postpaid" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="mms1" + mmsc="http://10.3.3.133:9090/was" + mmsproxy="10.3.2.133" + mmsport="8080" + type="mms" + /> + + <apn carrier="Mobily MMS Prepaid" + carrier_id = "1684" + mcc="420" + mnc="03" + apn="mms2" + mmsc="http://10.3.3.133:9090/was" + mmsproxy="10.3.2.133" + mmsport="8080" + type="mms" + /> + + <apn carrier="zain-Internet Wap" + carrier_id = "1972" + mcc="420" + mnc="04" + apn="zain" + authtype="0" + type="default,supl" + /> + + <apn carrier="zain-mms" + carrier_id = "1972" + mcc="420" + mnc="04" + apn="zainmms" + mmsc="http://10.122.200.12:8002" + mmsproxy="10.122.200.10" + mmsport="8080" + type="mms" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="SabaFon" + carrier_id = "1877" + mcc="421" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Sabafon MMS" + carrier_id = "1877" + mcc="421" + mnc="01" + apn="mms" + type="mms" + user="wap" + password="wap" + authtype="0" + mmsproxy="192.168.30.174" + mmsc="http://mms.sabafon.com/" + mmsport="8080" + /> + + <apn carrier="MTN" + carrier_id = "1878" + mcc="421" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN MMS YE" + carrier_id = "1878" + mcc="421" + mnc="02" + apn="fast-mms" + type="mms" + user="mms" + authtype="0" + mmsproxy="192.168.97.1" + mmsc="http://192.168.97.1/mmsc" + mmsport="3130" + /> + + <apn carrier="YemenMobile" + carrier_id = "2349" + mcc="421" + mnc="03" + apn="ymobile" + user="ymobile" + password="ymobile" + authtype="3" + type="default,supl" + /> + + <apn carrier="HiTS-UNITEL" + carrier_id = "2168" + mcc="421" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="YemenMobile" + carrier_id = "2349" + mcc="421" + mnc="11" + apn="ymdata" + authtype="0" + type="default,mms,supl,fota,cbs,dun" + protocol="IPV4V6" + /> + + <apn carrier="YemenMobile" + carrier_id = "2349" + mcc="421" + mnc="11" + apn="ymims" + authtype="0" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="Oman Mobile MMS" + carrier_id = "970" + mcc="422" + mnc="02" + apn="mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mmsc.omanmobile.om:10021/mmsc" + mmsproxy="192.168.203.35" + mmsport="8080" + type="mms" + /> + + + <apn carrier="Oman Mobile Internet" + carrier_id = "970" + mcc="422" + mnc="02" + apn="taif" + user="taif" + password="taif" + authtype="1" + type="default,supl" + /> + + <apn carrier="Nawras MMS" + carrier_id = "971" + mcc="422" + mnc="03" + apn="mms.nawras.com.om" + user="test" + password="test" + authtype="1" + mmsc="http://10.128.240.16/servlets/mms" + mmsproxy="10.128.240.19" + mmsport="8080" + type="mms" + /> + + + <apn carrier="Nawras Internet" + carrier_id = "971" + mcc="422" + mnc="03" + apn="isp.nawras.com.om" + user="test" + password="test" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Etisalat Data Package" + carrier_id = "451" + mcc="424" + mnc="02" + apn="etisalat.ae" + authtype="1" + type="default,supl" + /> + + <apn carrier="Weyak Wap" + carrier_id = "451" + mcc="424" + mnc="02" + apn="etisalat" + proxy="10.12.0.32" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="Etisalat MMS" + carrier_id = "451" + mcc="424" + mnc="02" + apn="etisalat" + mmsc="http://mms/servlets/mms" + mmsproxy="10.12.0.32" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="du Internet" + carrier_id = "1970" + mcc="424" + mnc="03" + apn="du" + type="default,supl" + /> + + <apn carrier="du WAP" + carrier_id = "1970" + mcc="424" + mnc="03" + apn="du" + proxy="10.19.18.4" + port="8080" + type="default,supl" + /> + + <apn carrier="du MMS" + carrier_id = "1970" + mcc="424" + mnc="03" + apn="du" + mmsc="http://mms.du.ae:8002" + mmsproxy="10.19.18.4" + mmsport="8080" + type="mms" + /> + + <apn carrier="3G Portal" + carrier_id = "796" + mcc="425" + mnc="01" + apn="uwap.orange.co.il" + mmsc="http://192.168.220.15/servlets/mms" + mmsproxy="192.118.11.55" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Cellcom Internet" + carrier_id = "797" + mcc="425" + mnc="02" + apn="sphone" + type="default,supl" + /> + + <apn carrier="Cellcom MMS" + carrier_id = "797" + mcc="425" + mnc="02" + apn="mms" + mmsc="http://mms.cellcom.co.il" + mmsproxy="vwapm2.ain.co.il" + mmsport="8080" + type="mms" + /> + + <apn carrier="Multimedia Pelephone" + carrier_id = "798" + mcc="425" + mnc="03" + apn="mms.pelephone.net.il" + user="pcl@3g" + password="pcl" + authtype="3" + mmsc="http://mmsu.pelephone.net.il" + mmsproxy="10.170.252.104" + mmsport="9093" + type="mms" + /> + + <apn carrier="Sphone Pelephone" + carrier_id = "798" + mcc="425" + mnc="03" + apn="sphone.pelephone.net.il" + user="pcl@3g" + password="pcl" + authtype="2" + type="default,supl" + /> + + <apn carrier="Jawwal WAP" + mcc="425" + mnc="05" + apn="wap" + proxy="213.244.118.129" + port="8080" + type="default,supl" + /> + + <apn carrier="Jawwal MMS" + mcc="425" + mnc="05" + apn="mms" + mmsc="http://mms.jawwal.ps/servlets/mms" + mmsproxy="213.244.118.129" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + mcc="425" + mnc="06" + apn="internet" + proxy="10.100.129.111" + port="8080" + type="default,supl" + /> + + <apn carrier="Wataniya_mms" + mcc="425" + mnc="06" + apn="mms" + mmsc="http://mms.wataniya.ps/servlets/mms" + mmsproxy="10.100.129.111" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet HOT mobile" + carrier_id = "1991" + mcc="425" + mnc="07" + apn="net.hotm" + type="default,supl" + /> + + <apn carrier="PC HOT mobile" + carrier_id = "1991" + mcc="425" + mnc="07" + apn="pc.hotm" + type="dun" + authtype="0" + /> + + <apn carrier="MMS HOT mobile" + carrier_id = "1991" + mcc="425" + mnc="07" + apn="mms.hotm" + mmsc="http://mms.hotmobile.co.il" + mmsproxy="80.246.131.99" + mmsport="80" + type="mms" + /> + + <apn carrier="GolanTelecom Internet" + carrier_id = "1990" + mcc="425" + mnc="08" + apn="internet.golantelecom.net.il" + type="default,supl" + /> + + <apn carrier="GolanTelecom MMS" + carrier_id = "1990" + mcc="425" + mnc="08" + apn="mms.golantelecom.net.il" + mmsc="http://mmsc.golantelecom.co.il" + mmsproxy="10.224.228.81" + mmsport="80" + type="mms" + /> + + <apn carrier="3G Portal" + carrier_id = "796" + mcc="425" + mnc="10" + apn="uwap.orange.co.il" + mmsc="http://192.168.220.15/servlets/mms" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="YouPhone" + carrier_id = "2169" + mcc="425" + mnc="14" + apn="data.youphone.co.il" + mmsc="http://192.168.220.15/servlets/mms" + type="default,supl,mms" + /> + + <apn carrier="Home Cellular Internet" + carrier_id = "2170" + mcc="425" + mnc="15" + apn="hcminternet" + type="default,supl" + /> + + <apn carrier="Home Cellular MMS" + carrier_id = "2170" + mcc="425" + mnc="15" + apn="hcmMMS" + mmsc="http://82.166.164.229:9000/mmsc" + mmsproxy="82.166.164.229" + mmsport="8898" + type="mms" + /> + + <apn carrier="Rami Levi 3G" + carrier_id = "2171" + mcc="425" + mnc="16" + apn="internet.rl" + type="default,supl" + /> + + <apn carrier="Rami Levi Multimedia" + carrier_id = "2171" + mcc="425" + mnc="16" + apn="mms.pelephone.net.il" + mmsc="http://mmsu.pelephone.net.il" + mmsproxy="10.170.252.104" + mmsport="9093" + type="mms" + /> + + <apn carrier="Annatel" + carrier_id = "2454" + mcc="425" + mnc="26" + apn="annatel" + type="default,supl" + /> + + <apn carrier="Batelco Internet" + carrier_id = "1372" + mcc="426" + mnc="01" + apn="internet.batelco.com" + type="default,supl" + /> + + <apn carrier="Batelco WAP" + carrier_id = "1372" + mcc="426" + mnc="01" + apn="wap.batelco.com" + user="wap" + password="wap" + authtype="0" + proxy="192.168.1.2" + port="80" + type="default,supl" + /> + + <apn carrier="Batelco MMS" + carrier_id = "1372" + mcc="426" + mnc="01" + apn="mms.batelco.com" + user="mms" + password="mms" + authtype="0" + mmsc="http://192.168.36.10/servlets/mms" + mmsproxy="192.168.1.2" + mmsport="80" + type="mms" + /> + + <apn carrier="Zain BH Internet" + carrier_id = "2014" + mcc="426" + mnc="02" + apn="internet" + user="internet" + password="internet" + authtype="0" + type="default,supl" + /> + + <apn carrier="Zain BH WAP" + carrier_id = "2014" + mcc="426" + mnc="02" + apn="wap" + user="wap" + password="wap" + authtype="0" + proxy="172.18.85.33" + port="80" + type="default,supl" + /> + + + <apn carrier="Zain BH MMS" + carrier_id = "2014" + mcc="426" + mnc="02" + apn="mms" + user="mms" + password="mms" + authtype="0" + mmsc="http://172.18.83.129:80/" + mmsproxy="172.18.85.34" + mmsport="80" + type="mms" + /> + + <apn carrier="VIVAGPRS" + carrier_id = "2015" + mcc="426" + mnc="04" + apn="viva.bh" + type="default,supl" + /> + + <apn carrier="VIVAWAP" + carrier_id = "2015" + mcc="426" + mnc="04" + apn="vivawap.bh" + proxy="172.18.142.36" + port="8080" + type="default,supl" + /> + + <apn carrier="VIVAMMS" + carrier_id = "2015" + mcc="426" + mnc="04" + apn="vivawap.bh" + mmsc="http://mms.viva.com.bh:38090" + mmsproxy="172.18.142.36" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1675" + mcc="427" + mnc="01" + apn="data" + type="default,supl" + authtype="1" + /> + + <apn carrier="MMS" + carrier_id = "1675" + mcc="427" + mnc="01" + apn="data" + mmsc="http://mmsr.ooredoomms.qa" + mmsproxy="10.23.8.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="Voda internet" + carrier_id = "2393" + mcc="427" + mnc="02" + apn="web.vodafone.com.qa" + type="default,supl" + /> + + <apn carrier="VFQ MMS" + carrier_id = "2393" + mcc="427" + mnc="02" + apn="vodafone.com.qa" + mmsc="http://mms.vodafone.com.qa/mmsc" + mmsproxy="10.101.97.102" + mmsport="80" + type="mms" + /> + + <apn carrier="Unitel" + carrier_id = "2347" + mcc="428" + mnc="88" + apn="default" + type="default,supl" + /> + + <apn carrier="Skytel" + carrier_id = "2172" + mcc="428" + mnc="91" + apn="default" + type="default,supl" + /> + + <apn carrier="G.Mobile" + carrier_id = "2173" + mcc="428" + mnc="98" + apn="default" + type="default,supl" + /> + + <apn carrier="MobiCom" + carrier_id = "1612" + mcc="428" + mnc="99" + apn="default" + type="default,supl" + /> + + <apn carrier="Namaste / NT Mobile" + carrier_id = "962" + mcc="429" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Ncell" + carrier_id = "1923" + mcc="429" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Sky/C-Phone" + carrier_id = "962" + mcc="429" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="SmartCell" + carrier_id = "1924" + mcc="429" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="MCI-GPRS" + carrier_id = "1562" + mcc="432" + mnc="11" + apn="mcinet" + type="default,supl" + /> + + <apn carrier="MCCI MMS" + carrier_id = "1562" + mcc="432" + mnc="11" + apn="mcinet" + mmsc="http://192.168.193.134:38090/was" + mmsproxy="192.168.194.73" + mmsport="8080" + type="mms" + /> + + <apn carrier="MCI-GPRS" + carrier_id = "1563" + mcc="432" + mnc="14" + apn="mcinet" + type="default,supl" + /> + + <apn carrier="MCCI MMS" + carrier_id = "1563" + mcc="432" + mnc="14" + apn="MCI-GPRS" + mmsport="38090" + mmsc="http://192.168.193.134" + type="mms" + /> + + <apn carrier="MCI-GPRS" + carrier_id = "1564" + mcc="432" + mnc="19" + apn="mcinet" + type="default,supl" + /> + + <apn carrier="MCCI MMS" + carrier_id = "1564" + mcc="432" + mnc="19" + apn="MCI-GPRS" + mmsport="38090" + mmsc="http://192.168.193.134" + type="mms" + /> + + <apn carrier="rightel" + carrier_id = "1987" + mcc="432" + mnc="20" + apn="rightel" + type="default,supl" + /> + + <apn carrier="RighTel-MMS" + carrier_id = "1987" + mcc="432" + mnc="20" + apn="RighTel-WAP" + mmsc="http://10.200.40.55:38090/was" + mmsproxy="10.200.39.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Irancell-GPRS" + carrier_id = "1967" + mcc="432" + mnc="35" + apn="mtnirancell" + proxy="10.131.26.138" + port="8080" + type="default,supl" + /> + + <apn carrier="Irancell-MMS" + carrier_id = "1967" + mcc="432" + mnc="35" + apn="mtnirancell" + mmsc="http://mms:8002" + mmsproxy="10.131.26.138" + mmsport="8080" + type="mms" + /> + + <apn carrier="MCI-GPRS" + carrier_id = "2352" + mcc="432" + mnc="70" + apn="mcinet" + type="default,supl" + /> + + <apn carrier="MCCI MMS" + carrier_id = "2352" + mcc="432" + mnc="70" + apn="mcinet" + mmsc="http://192.168.193.134:38090/was" + mmsproxy="192.168.194.73" + mmsport="8080" + type="mms" + /> + + <apn carrier="MCI-GPRS" + carrier_id = "2358" + mcc="432" + mnc="93" + apn="mcinet" + type="default,supl" + /> + + <apn carrier="MCCI MMS" + carrier_id = "2358" + mcc="432" + mnc="93" + apn="MCI-GPRS" + mmsport="38090" + mmsc="http://192.168.193.134" + type="mms" + /> + + <apn carrier="Beeline-UZB Internet" + carrier_id = "1867" + mcc="434" + mnc="04" + apn="internet.beeline.uz" + user="beeline" + password="beeline" + authtype="1" + type="default,supl" + /> + + <apn carrier="Beeline-UZB MMS" + carrier_id = "1867" + mcc="434" + mnc="04" + apn="mms.beeline.uz" + user="beeline" + password="beeline" + authtype="1" + mmsc="http://mms" + mmsproxy="172.30.30.166" + mmsport="8080" + type="mms" + /> + + <apn carrier="UCELL Internet" + carrier_id = "1868" + mcc="434" + mnc="05" + apn="internet" + type="default,supl" + /> + + <apn carrier="UCELL MMS" + carrier_id = "1868" + mcc="434" + mnc="05" + apn="mms" + mmsc="http://mmsc:8002/" + mmsproxy="10.64.164.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Perfectum Mobile" + carrier_id = "2235" + mcc="434" + mnc="06" + apn="default" + type="default,supl" + /> + + <apn carrier="MTS-UZB Internet" + carrier_id = "1869" + mcc="434" + mnc="07" + apn="net.mts.uz" + user="mts" + password="mts" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTS-UZB MMS" + carrier_id = "1869" + mcc="434" + mnc="07" + apn="mms.mts.uz" + mmsc="http://mmsc/was" + mmsproxy="10.10.0.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Tcell" + carrier_id = "1724" + mcc="436" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Tcell" + carrier_id = "1725" + mcc="436" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Megafon" + carrier_id = "1726" + mcc="436" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Babilon-M" + carrier_id = "1727" + mcc="436" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Tacom" + carrier_id = "1728" + mcc="436" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Tcell" + carrier_id = "2174" + mcc="436" + mnc="12" + apn="default" + type="default,supl" + /> + + <apn carrier="Beeline" + carrier_id = "867" + mcc="437" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Fonex" + carrier_id = "2175" + mcc="437" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="MegaCom" + carrier_id = "2176" + mcc="437" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="O!" + carrier_id = "2177" + mcc="437" + mnc="09" + apn="default" + type="default,supl" + /> + + <apn carrier="MTS (BARASH Communication)" + carrier_id = "1729" + mcc="438" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="TM-Cell" + carrier_id = "1730" + mcc="438" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="IIJmio (TypeI)" + mcc="440" + mnc="03" + apn="iijmio.jp" + user="mio@iij" + password="iij" + authtype="3" + protocol="IPV4V6" + type="default" + roaming_protocol="IP" + /> + + <apn carrier="vmobile.jp" + mcc="440" + mnc="03" + apn="vmobile.jp" + user="vmobile@jp" + password="vmobile" + authtype="3" + protocol="IPV4V6" + type="default" + roaming_protocol="IP" + /> + + <apn carrier="spモード" + mcc="440" + mnc="10" + apn="spmode.ne.jp" + type="default,supl" + authtype="0" + protocol="IPV4V6" + /> + + <apn carrier="lte_ims" + mcc="440" + mnc="10" + apn="ims" + type="ims" + authtype="0" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + bearer_bitmask="14" + /> + + <apn carrier="Emergency" + mcc="440" + mnc="10" + apn="" + type="Emergency" + protocol="IPV6" + roaming_protocol="IPV6" + /> + + <apn carrier="楽天(rakuten.jp)" + carrier_id="2429" + mcc="440" + mnc="11" + apn="rakuten.jp" + type="default,supl,dun" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="IMS" + carrier_id="2429" + mcc="440" + mnc="11" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="SBM" + carrier_id = "1894" + mcc="440" + mnc="20" + apn="" + type="ia" + protocol="IP" + /> + + <apn carrier="IMS" + carrier_id = "1894" + mcc="440" + mnc="20" + apn="IMS" + type="ims" + protocol="IPV6" + /> + + <apn carrier="Application" + carrier_id = "1894" + mcc="440" + mnc="20" + apn="plus.acs.jp" + user="ym" + password="ym" + mmsproxy="andmms.plusacs.ne.jp" + mmsport="8080" + mmsc="http://mms-s" + type="default,mms,supl,hipri" + authtype="2" + /> + + <apn carrier="RATEL" + carrier_id = "1894" + mcc="440" + mnc="20" + apn="ratel.com" + user="ratel@ratel.com" + server="" + password="ratel" + authtype="3" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="RATEL" + carrier_id = "1581" + mcc="440" + mnc="51" + apn="ratel.com" + user="ratel@ratel.com" + server="" + password="ratel" + authtype="3" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="Rakuten" + carrier_id = "2109" + mcc="440" + mnc="51" + apn="a.rmobile.jp" + user="rakuten@vdm" + server="" + password="0000" + authtype="3" + type="default,supl" + /> + + <apn carrier="SKT IA" + carrier_id = "1891" + mcc="450" + mnc="05" + apn="" + type="ia" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="SKT IMS" + carrier_id = "1891" + mcc="450" + mnc="05" + apn="IMS" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="SKT LTE INTERNET" + carrier_id = "1891" + mcc="450" + mnc="05" + apn="lte.sktelecom.com" + type="default,mms,supl,fota,cbs" + mmsc="http://omms.nate.com:9082/oma_mms" + mmsproxy="smart.nate.com" + mmsport="9093" + server="*" + protocol="IPV4V6" + /> + + <apn carrier="LG uplus IA" + carrier_id = "1892" + mcc="450" + mnc="06" + apn="" + type="ia" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="LG uplus IMS" + carrier_id = "1892" + mcc="450" + mnc="06" + apn="IMS" + type="ims" + mmsc="http://omammsc.uplus.co.kr:9084" + protocol="IPV4V6" + /> + + <apn carrier="LG uplus" + carrier_id = "1892" + mcc="450" + mnc="06" + apn="internet.lguplus.co.kr" + type="default,mms,supl,fota,cbs" + mmsc="http://omammsc.uplus.co.kr:9084" + protocol="IPV4V6" + /> + + <apn carrier="KT IA" + carrier_id = "1890" + mcc="450" + mnc="08" + apn="" + type="ia" + protocol="IPV4V6" + roaming_protocol="IP" + /> + + <apn carrier="KT IMS" + carrier_id = "1890" + mcc="450" + mnc="08" + apn="IMS" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="KT" + carrier_id = "1890" + mcc="450" + mnc="08" + apn="lte.ktfwing.com" + type="default,mms,supl,fota,cbs" + mmsc="http://mmsc.ktfwing.com:9082" + port="80" + server="*" + /> + + <apn carrier="Mobi-wap-gprs 2" + carrier_id = "1299" + mcc="452" + mnc="01" + apn="m-wap" + user="mms" + password="mms" + authtype="1" + type="default,supl" + /> + + <apn carrier="Mobi-wap-gprs 1" + carrier_id = "1299" + mcc="452" + mnc="01" + apn="m-wap" + user="mms" + password="mms" + authtype="1" + proxy="203.162.21.107" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobi-gprs-mms" + carrier_id = "1299" + mcc="452" + mnc="01" + apn="m-i090" + user="mms" + password="mms" + authtype="1" + mmsc="http://203.162.21.114/mmsc" + mmsproxy="203.162.21.114" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vina-wap-gprs" + carrier_id = "1300" + mcc="452" + mnc="02" + apn="m3-world" + user="mms" + password="mms" + authtype="1" + type="default,supl" + /> + + <apn carrier="Vina-gprs-mms" + carrier_id = "1300" + mcc="452" + mnc="02" + apn="m3-mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.vinaphone.com.vn" + mmsproxy="10.1.10.46" + mmsport="8000" + type="mms" + /> + + <apn carrier="Viettel-wap-gprs 1" + carrier_id = "1899" + mcc="452" + mnc="04" + apn="v-internet" + type="default,supl" + /> + + <apn carrier="Viettel-wap-gprs 2" + carrier_id = "1899" + mcc="452" + mnc="04" + apn="v-wap" + proxy="192.168.233.10" + port="8080" + type="default,supl" + /> + + <apn carrier="Viettel-gprs-mms" + carrier_id = "1899" + mcc="452" + mnc="04" + apn="v-mms" + mmsc="http://mms.viettelmobile.com.vn/mms/wapenc" + mmsproxy="192.168.233.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="Vietnamobile_GPRS3" + carrier_id = "1994" + mcc="452" + mnc="05" + apn="internet" + type="default,supl" + /> + + <apn carrier="Vietnamobile_GPRS1" + carrier_id = "1994" + mcc="452" + mnc="05" + apn="wap" + proxy="10.10.128.44" + port="8080" + type="default,supl" + /> + + <apn carrier="Vietnamobile_GPRS2" + carrier_id = "1994" + mcc="452" + mnc="05" + apn="wap" + type="default,supl" + /> + + <apn carrier="Vietnamobile_MMS" + carrier_id = "1994" + mcc="452" + mnc="05" + apn="mms" + mmsc="http://10.10.128.58/servlets/mms" + mmsproxy="10.10.128.44" + mmsport="8080" + type="mms" + /> + + <apn carrier="Gmobile-wap-gprs2" + carrier_id = "2178" + mcc="452" + mnc="07" + apn="internet" + type="default,supl" + /> + + <apn carrier="Gmobile-wap-gprs" + carrier_id = "2178" + mcc="452" + mnc="07" + apn="internet" + proxy="10.16.70.199" + port="8080" + type="default,supl" + /> + + <apn carrier="Gmobile-gprs-mms" + carrier_id = "2178" + mcc="452" + mnc="07" + apn="mms" + mmsc="http://mms" + mmsproxy="10.16.70.199" + mmsport="8080" + type="mms" + /> + + <apn carrier="Gmobile MMS" + carrier_id = "2178" + mcc="452" + mnc="07" + apn="mms" + user="mms" + password="mms" + authtype="2" + mmsc="http://mms" + mmsproxy="10.16.70.199" + mmsport="8080" + type="mms" + /> + + <apn carrier="e-internet" + carrier_id = "2179" + mcc="452" + mnc="08" + apn="e-internet" + type="default,supl" + /> + + <apn carrier="e-wap" + carrier_id = "2179" + mcc="452" + mnc="08" + apn="e-wap" + proxy="10.18.2.183" + port="8080" + type="default,supl" + /> + + <apn carrier="e-mms" + carrier_id = "2179" + mcc="452" + mnc="08" + apn="e-mms" + mmsc="http://10.18.2.172:38090" + mmsproxy="10.18.2.183" + mmsport="8080" + type="mms" + /> + + <apn carrier="1O1O" + carrier_id = "1526" + mcc="454" + mnc="00" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="one2free" + carrier_id = "1526" + mcc="454" + mnc="00" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="NWMOBILE" + carrier_id = "1526" + mcc="454" + mnc="00" + apn="NWMOBILE" + mmsproxy="192.168.59.61" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="1O1O" + carrier_id = "759" + mcc="454" + mnc="02" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="one2free" + carrier_id = "759" + mcc="454" + mnc="02" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="NWMOBILE" + carrier_id = "759" + mcc="454" + mnc="02" + apn="NWMOBILE" + mmsproxy="192.168.59.61" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="3 LTE" + carrier_id = "760" + mcc="454" + mnc="03" + apn="mobile.lte.three.com.hk" + mmsc="http://mms.um.three.com.hk:10021/mmsc" + mmsproxy="mms.three.com.hk" + mmsport="8799" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="3" + carrier_id = "760" + mcc="454" + mnc="03" + apn="mobile.three.com.hk" + mmsc="http://mms.um.three.com.hk:10021/mmsc" + mmsproxy="mms.three.com.hk" + mmsport="8799" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="3(2G) MMS" + carrier_id = "1960" + mcc="454" + mnc="04" + apn="mms-g.three.com.hk" + mmsc="http://10.30.15.51:10021/mmsc" + mmsproxy="10.30.15.53" + mmsport="8080" + type="mms" + /> + + <apn carrier="3(2G) GPRS" + carrier_id = "1960" + mcc="454" + mnc="04" + apn="web-g.three.com.hk" + proxy="10.30.3.151" + port="8080" + type="default,supl" + /> + + <apn carrier="SmarTone" + carrier_id = "761" + mcc="454" + mnc="06" + apn="SmarTone" + mmsc="http://mms.smartone.com/server" + mmsproxy="10.9.9.9" + mmsport="8080" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="454" + mnc="08" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="one2free" + carrier_id = "765" + mcc="454" + mnc="10" + apn="hkcsl" + mmsc="http://192.168.58.171:8002" + mmsproxy="192.168.59.51" + mmsport="8080" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="CMHK MMS" + carrier_id = "767" + mcc="454" + mnc="12" + apn="cmhk" + mmsc="http://mms.hk.chinamobile.com/mms" + type="mms" + /> + + <apn carrier="CMHK Data" + carrier_id = "767" + mcc="454" + mnc="12" + apn="cmhk" + type="default,supl" + /> + + <apn carrier="CMHK MMS" + carrier_id = "767" + mcc="454" + mnc="13" + apn="cmhk" + mmsc="http://mms.hk.chinamobile.com/mms" + type="mms" + /> + + <apn carrier="CMHK Data" + carrier_id = "767" + mcc="454" + mnc="13" + apn="cmhk" + type="default,supl" + /> + + <apn carrier="SmarTone" + carrier_id = "768" + mcc="454" + mnc="15" + apn="SmarTone" + mmsproxy="10.9.9.9" + mmsport="8080" + mmsc="http://mms.smartone.com/server" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="PCCW-HKT" + carrier_id = "769" + mcc="454" + mnc="16" + apn="pccw" + mmsc="http://3gmms.pccwmobile.com:8080/was" + mmsproxy="10.140.14.10" + mmsport="8080" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="SmarTone" + carrier_id = "761" + mcc="454" + mnc="17" + apn="SmarTone" + mmsproxy="10.9.9.9" + mmsport="8080" + mmsc="http://mms.smartone.com/server" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="1O1O" + carrier_id = "770" + mcc="454" + mnc="18" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="one2free" + carrier_id = "770" + mcc="454" + mnc="18" + apn="mobile" + mmsproxy="192.168.59.51" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="NWMOBILE" + carrier_id = "770" + mcc="454" + mnc="18" + apn="NWMOBILE" + mmsproxy="192.168.59.61" + mmsport="8080" + mmsc="http://192.168.58.171:8002" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="PCCW-HKT" + carrier_id = "1526" + mcc="454" + mnc="19" + apn="pccw" + mmsc="http://3gmms.pccwmobile.com:8080/was" + mmsproxy="10.140.14.10" + mmsport="8080" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="SmarTone Macau" + carrier_id = "1613" + mcc="455" + mnc="00" + apn="smartgprs" + mmsc="http://momms.smartone.com/dmog/mo" + mmsproxy="10.9.9.29" + mmsport="8080" + authtype="3" + type="default,supl,mms" + /> + + <apn carrier="CTM Data" + carrier_id = "1614" + mcc="455" + mnc="01" + apn="ctm-mobile" + type="default,supl" + /> + + <apn carrier="CTM MMS" + carrier_id = "1614" + mcc="455" + mnc="01" + apn="ctmmms" + mmsc="http://mms.wap.ctm.net:8002" + mmsproxy="192.168.99.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="CTM (Prepaid)" + carrier_id = "1614" + mcc="455" + mnc="01" + apn="ctmprepaid" + mmsc="http://mms.wap.ctm.net:8002" + mmsproxy="192.168.99.3" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="3 Macau" + carrier_id = "1615" + mcc="455" + mnc="03" + apn="mobile.three.com.mo" + mmsc="http://mms.three.com.mo:10021/mmsc" + mmsproxy="mms.three.com.mo" + mmsport="8080" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="CTM Data" + carrier_id = "1614" + mcc="455" + mnc="04" + apn="ctm-mobile" + type="default,supl" + /> + + <apn carrier="CTM MMS" + carrier_id = "1614" + mcc="455" + mnc="04" + apn="ctmmms" + mmsc="http://mms.wap.ctm.net:8002" + mmsproxy="192.168.99.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="CTM (Prepaid)" + carrier_id = "1614" + mcc="455" + mnc="04" + apn="ctmprepaid" + mmsc="http://mms.wap.ctm.net:8002" + mmsproxy="192.168.99.3" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="3 Macau" + mcc="455" + mnc="05" + apn="mobile.three.com.mo" + mmsc="http://mms.three.com.mo:10021/mmsc" + mmsproxy="mms.three.com.mo" + mmsport="8080" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="Cellcard" + carrier_id = "868" + mcc="456" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Smart" + carrier_id = "869" + mcc="456" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="qb" + carrier_id = "2180" + mcc="456" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Star-Cell" + carrier_id = "869" + mcc="456" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Smart" + carrier_id = "869" + mcc="456" + mnc="06" + apn="default" + type="default,supl" + /> + + <apn carrier="Metfone" + carrier_id = "2181" + mcc="456" + mnc="08" + apn="default" + type="default,supl" + /> + + <apn carrier="Beeline" + mcc="456" + mnc="09" + apn="default" + type="default,supl" + /> + + <apn carrier="Excell" + carrier_id = "2236" + mcc="456" + mnc="11" + apn="default" + type="default,supl" + /> + + <apn carrier="Cellcard" + carrier_id = "871" + mcc="456" + mnc="18" + apn="default" + type="default,supl" + /> + + <apn carrier="LTC" + carrier_id = "1590" + mcc="457" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="ETL" + carrier_id = "1591" + mcc="457" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Unitel" + carrier_id = "2346" + mcc="457" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Beeline" + carrier_id = "1592" + mcc="457" + mnc="08" + apn="default" + type="default,supl" + /> + + <apn carrier="中国移动 (China Mobile) GPRS" + carrier_id = "1435" + mcc="460" + mnc="00" + apn="cmnet" + type="default,supl" + /> + + <apn carrier="中国移动 (China Mobile) WAP" + carrier_id = "1435" + mcc="460" + mnc="00" + apn="cmwap" + proxy="10.0.0.172" + port="80" + type="default,supl" + /> + + <apn carrier="中国移动彩信 (China Mobile)" + carrier_id = "1435" + mcc="460" + mnc="00" + apn="cmwap" + proxy="10.0.0.172" + port="80" + mmsc="http://mmsc.monternet.com" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="沃3G连接互联网 (China Unicom)" + carrier_id = "1436" + mcc="460" + mnc="01" + apn="3gnet" + type="default,supl" + /> + + <apn carrier="沃3G手机上网 (China Unicom)" + carrier_id = "1436" + mcc="460" + mnc="01" + apn="3gwap" + proxy="10.0.0.172" + port="80" + type="default,supl" + /> + + <apn carrier="联通2GNET上网 (China Unicom)" + carrier_id = "1436" + mcc="460" + mnc="01" + apn="uninet" + type="default,supl" + /> + + <apn carrier="联通彩信 (China Unicom)" + carrier_id = "1436" + mcc="460" + mnc="01" + apn="3gwap" + mmsc="http://mmsc.myuni.com.cn" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="联通2g彩信 (China Unicom)" + carrier_id = "1436" + mcc="460" + mnc="01" + apn="uniwap" + mmsc="http://mmsc.myuni.com.cn" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="中国移动 (China Mobile) GPRS" + carrier_id = "1435" + mcc="460" + mnc="02" + apn="cmnet" + type="default,supl" + /> + + <apn carrier="中国移动 (China Mobile) WAP" + carrier_id = "1435" + mcc="460" + mnc="02" + apn="cmwap" + proxy="10.0.0.172" + port="80" + type="default,supl" + /> + + <apn carrier="中国移动彩信 (China Mobile)" + carrier_id = "1435" + mcc="460" + mnc="02" + apn="cmwap" + proxy="10.0.0.172" + port="80" + mmsc="http://mmsc.monternet.com" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="中国移动 (China Mobile) GPRS" + carrier_id = "1435" + mcc="460" + mnc="07" + apn="cmnet" + type="default,supl" + /> + + <apn carrier="中国移动 (China Mobile) GPRS" + carrier_id = "1435" + mcc="460" + mnc="08" + apn="cmnet" + type="default,supl" + /> + + <apn carrier="中国移动 (China Mobile) WAP" + carrier_id = "1435" + mcc="460" + mnc="07" + apn="cmwap" + proxy="10.0.0.172" + port="80" + type="default,supl" + /> + + <apn carrier="中国移动彩信 (China Mobile)" + carrier_id = "1435" + mcc="460" + mnc="07" + apn="cmwap" + proxy="10.0.0.172" + port="80" + mmsc="http://mmsc.monternet.com" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="中国移动 (China Mobile) WAP" + carrier_id = "1435" + mcc="460" + mnc="08" + apn="cmwap" + proxy="10.0.0.172" + port="80" + type="default,supl" + /> + + <apn carrier="中国移动彩信 (China Mobile)" + carrier_id = "1435" + mcc="460" + mnc="08" + apn="cmwap" + proxy="10.0.0.172" + port="80" + mmsc="http://mmsc.monternet.com" + mmsproxy="10.0.0.172" + mmsport="80" + type="mms" + /> + + <apn carrier="China Unicom 3G" + apn="3gnet" + carrier_id = "1436" + mcc="460" + mnc="09" + port="80" + type="default, supl"/> + + <apn carrier="China Unicom wap" + apn="3gwap" + carrier_id = "1436" + mcc="460" + mnc="09" + proxy="10.0.0.172" + port="80" + mmsproxy="10.0.0.172" + mmsport="80" + mmsc="http://mmsc.myuni.com.cn" + type="default, mms"/> + + <apn carrier="ctlte" + carrier_id = "2237" + mcc="460" + mnc="11" + apn="ctlte" + user="" + password="" + authtype="0" + server="*" + proxy="" + port="80" + mmsc="" + mmsproxy="" + mmsport="" + type="default,hipri,supl,fota,cbs" + protocol="IPV4V6" + /> + + <apn carrier="CTWAP" + carrier_id = "2237" + mcc="460" + mnc="11" + apn="ctwap" + user="" + password="" + authtype="0" + server="*" + proxy="" + port="80" + mmsc="http://mmsc.vnet.mobi" + mmsproxy="10.0.0.200" + mmsport="80" + type="mms" + protocol="IPV4V6" + /> + + <apn carrier="CTNET" + carrier_id = "2237" + mcc="460" + mnc="03" + apn="ctnet" + user="ctnet@mycdma.cn" + password="vnet.mobi" + authtype="3" + server="*" + proxy="" + port="80" + mmsc="" + mmsproxy="" + mmsport="" + type="default,hipri,fota,cbs" + protocol="IP" + /> + + <apn carrier="CTWAP" + carrier_id = "2237" + mcc="460" + mnc="03" + apn="ctwap" + user="ctwap@mycdma.cn" + password="vnet.mobi" + authtype="3" + server="*" + proxy="" + port="80" + mmsc="http://mmsc.vnet.mobi" + mmsproxy="10.0.0.200" + mmsport="80" + type="default,mms,hipri,supl,fota,cbs" + protocol="IP" + /> + + <apn carrier="CTNET" + carrier_id = "2237" + mcc="204" + mnc="04" + apn="ctnet" + user="" + password="" + authtype="0" + server="*" + proxy="" + port="" + mmsc="" + mmsproxy="" + mmsport="" + type="default,hipri,supl,fota,cbs" + mvno_type="spn" + mvno_match_data="中国电信" + protocol="IP" + /> + + <apn carrier="遠傳電信(Far EasTone) (MMS)" + carrier_id = "1881" + mcc="466" + mnc="01" + apn="fetnet01" + mmsc="http://mms" + mmsproxy="210.241.199.199" + mmsport="9201" + type="mms" + /> + + <apn carrier="遠傳電信(Far EasTone) (Internet)" + carrier_id = "1881" + mcc="466" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="和信電訊(KGT-Online) (Internet)" + carrier_id = "1881" + mcc="466" + mnc="88" + apn="internet" + type="default,supl" + /> + + <apn carrier="和信電訊(KGT-Online) (MMS)" + carrier_id = "1881" + mcc="466" + mnc="88" + apn="kgtmms" + mmsc="http://mms.kgtmms.net.tw/mms/wapenc" + mmsproxy="172.28.33.5" + mmsport="8080" + type="mms" + /> + + <apn carrier="VIBO-vibo" + carrier_id = "1886" + mcc="466" + mnc="89" + apn="vibo" + type="default,supl" + /> + + <apn carrier="T Star-internet" + carrier_id = "1886" + mcc="466" + mnc="89" + apn="internet" + type="default,supl" + /> + + <apn carrier="VIBOONE" + carrier_id = "1886" + mcc="466" + mnc="89" + apn="viboone" + type="default,supl" + /> + + <apn carrier="T Star-MMS" + carrier_id = "1886" + mcc="466" + mnc="89" + apn="internet" + mmsc="http://mms.vibo.net.tw" + mmsproxy="172.24.128.36" + mmsport="8080" + type="mms" + /> + + <apn carrier="中華電信(Chunghwa) (Internet)" + carrier_id = "1884" + mcc="466" + mnc="92" + apn="internet" + type="default,supl" + /> + + <apn carrier="中華電信(Chunghwa) (MMS)" + carrier_id = "1884" + mcc="466" + mnc="92" + apn="emome" + mmsc="http://mms.emome.net:8002" + mmsproxy="10.1.1.1" + mmsport="8080" + type="mms" + /> + + <apn carrier="台灣大哥大(TW Mobile) (Internet)" + carrier_id = "1887" + mcc="466" + mnc="93" + apn="Internet" + type="default,supl" + /> + + <apn carrier="台灣大哥大(TW Mobile) (MMS)" + carrier_id = "1887" + mcc="466" + mnc="93" + apn="MMS" + mmsc="http://mms.catch.net.tw" + mmsproxy="10.1.1.2" + mmsport="80" + type="mms" + /> + + <apn carrier="台灣大哥大(TW Mobile) (Internet)" + carrier_id = "1888" + mcc="466" + mnc="97" + apn="Internet" + type="default,supl" + /> + + <apn carrier="台灣大哥大(TW Mobile) (MMS)" + carrier_id = "1888" + mcc="466" + mnc="97" + apn="MMS" + mmsc="http://mms.catch.net.tw" + mmsproxy="10.1.1.2" + mmsport="80" + type="mms" + /> + + <apn carrier="台灣大哥大(TW Mobile) (Internet)" + carrier_id = "1889" + mcc="466" + mnc="99" + apn="Internet" + type="default,supl" + /> + + <apn carrier="台灣大哥大(TW Mobile) (MMS)" + carrier_id = "1889" + mcc="466" + mnc="99" + apn="mms" + mmsc="http://mms.catch.net.tw" + mmsproxy="10.1.1.2" + mmsport="80" + type="mms" + /> + + <apn carrier="GP-INTERNET" + carrier_id = "1362" + mcc="470" + mnc="01" + apn="gpinternet" + authtype="0" + type="default,supl,agps,fota,dun" + /> + + <apn carrier="GP-MMS" + carrier_id = "1362" + mcc="470" + mnc="01" + apn="gpmms" + authtype="0" + mmsc="http://mms.gpsurf.net/servlets/mms" + mmsproxy="10.128.1.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Dhiraagu" + carrier_id = "1624" + mcc="472" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="OoredooData" + carrier_id = "2033" + mcc="472" + mnc="02" + apn="OoredooData" + type="default" + /> + + <apn carrier="MMS" + carrier_id = "2033" + mcc="472" + mnc="02" + apn="OoredooData" + mmsc="http://mms.ooredoo.mv" + mmsproxy="172.24.10.20" + mmsport="8080" + type="mms" + /> + + <apn carrier="DiGi Internet" + carrier_id = "1630" + mcc="502" + mnc="10" + apn="diginet" + type="default,supl" + /> + + <apn carrier="DiGi MMS" + carrier_id = "1630" + mcc="502" + mnc="10" + apn="digimms" + user="mms" + password="mms" + mmsc="http://mms.digi.com.my/servlets/mms" + mmsproxy="203.92.128.160" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Maxis Internet" + carrier_id = "1628" + mcc="502" + mnc="12" + apn="max4g" + user="maxis" + password="wap" + mmsproxy="202.75.133.49" + mmsport="80" + mmsc="http://172.16.74.100:10021/mmsc" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="Celcom Internet" + carrier_id = "1633" + mcc="502" + mnc="13" + apn="celcom4g" + mmsproxy="10.128.1.242" + mmsport="8080" + mmsc="http://mms.celcom.net.my" + type="default,supl,mms" + /> + + <apn carrier="DiGi Internet" + carrier_id = "1630" + mcc="502" + mnc="143" + apn="diginet" + type="default,supl" + /> + + <apn carrier="DiGi MMS" + carrier_id = "1630" + mcc="502" + mnc="143" + apn="digimms" + user="mms" + password="mms" + mmsc="http://mms.digi.com.my/servlets/mms" + mmsproxy="203.92.128.160" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Celcom Internet" + carrier_id = "1633" + mcc="502" + mnc="145" + apn="celcom4g" + mmsproxy="10.128.1.242" + mmsport="8080" + mmsc="http://mms.celcom.net.my" + type="default,supl,mms" + /> + + <apn carrier="DiGi Internet" + carrier_id = "1630" + mcc="502" + mnc="146" + apn="diginet" + type="default,supl" + /> + + <apn carrier="DiGi MMS" + carrier_id = "1630" + mcc="502" + mnc="146" + apn="digimms" + user="mms" + password="mms" + mmsc="http://mms.digi.com.my/servlets/mms" + mmsproxy="203.92.128.160" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="Celcom Internet" + carrier_id = "1633" + mcc="502" + mnc="148" + apn="celcom4g" + mmsproxy="10.128.1.242" + mmsport="8080" + mmsc="http://mms.celcom.net.my" + type="default,supl,mms" + /> + + <apn carrier="DiGi MMS" + carrier_id = "1630" + mcc="502" + mnc="16" + apn="digimms" + user="mms" + password="mms" + mmsc="http://mms.digi.com.my/servlets/mms" + mmsproxy="203.92.128.160" + mmsport="80" + authtype="1" + type="mms" + /> + + <apn carrier="DiGi Internet" + carrier_id = "1630" + mcc="502" + mnc="16" + apn="diginet" + type="default,supl" + /> + + <apn carrier="Maxis Internet" + carrier_id = "1631" + mcc="502" + mnc="17" + apn="max4g" + user="maxis" + password="wap" + mmsproxy="202.75.133.49" + mmsport="80" + mmsc="http://172.16.74.100:10021/mmsc" + authtype="1" + type="default,supl,mms" + /> + + <apn carrier="U Mobile Internet" + carrier_id = "1632" + mcc="502" + mnc="18" + apn="my3g" + mmsproxy="10.30.5.11" + mmsport="8080" + mmsc="http://10.30.3.11/servlets/mms" + type="default,supl,mms" + /> + + <apn carrier="Celcom Internet" + carrier_id = "1633" + mcc="502" + mnc="19" + apn="celcom4g" + mmsproxy="10.128.1.242" + mmsport="8080" + mmsc="http://mms.celcom.net.my" + type="default,supl,mms" + /> + + <apn carrier="Telstra IMS" + carrier_id = "1345" + mcc="505" + mnc="01" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Telstra Internet" + carrier_id = "1345" + mcc="505" + mnc="01" + apn="telstra.wap" + type="default,supl" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra MMS" + carrier_id = "1345" + mcc="505" + mnc="01" + apn="telstra.mms" + type="mms" + mmsc="http://mmsc.telstra.com:8002/" + mmsproxy="10.1.1.180" + mmsport="80" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra Tethering" + carrier_id = "1345" + mcc="505" + mnc="01" + apn="telstra.internet" + type="dun" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra HOS" + carrier_id = "1345" + mcc="505" + mnc="01" + apn="hos" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Optus Yes Internet" + carrier_id = "30" + mcc="505" + mnc="02" + apn="yesinternet" + type="default,supl" + /> + + <apn carrier="Optus MMS" + carrier_id = "30" + mcc="505" + mnc="02" + apn="mms" + mmsc="http://mmsc.optus.com.au:8002/" + mmsproxy="61.88.190.10" + mmsport="8070" + type="mms" + /> + + <apn carrier="Virgin Internet" + carrier_id = "2145" + mcc="505" + mnc="02" + apn="yesinternet" + type="default,supl" + mvno_match_data="505029" + mvno_type="imsi" + /> + + <apn carrier="Virgin MMS" + carrier_id = "2145" + mcc="505" + mnc="02" + apn="mms" + mmsc="http://mmsc.optus.com.au:8002/" + mmsproxy="61.88.190.10" + mmsport="8070" + type="mms" + mvno_match_data="505029" + mvno_type="imsi" + /> + + <apn carrier="Vodafone live!" + carrier_id = "15" + mcc="505" + mnc="03" + apn="live.vodafone.com" + mmsc="http://pxt.vodafone.net.au/pxtsend" + mmsproxy="10.202.2.60" + mmsport="8080" + type="default,supl,mms" + /> + + <apn carrier="Planet 3" + carrier_id = "1348" + mcc="505" + mnc="06" + apn="3services" + authtype="0" + mmsc="http://mmsc.three.net.au:10021/mmsc" + mmsproxy="10.176.57.25" + mmsport="8799" + protocol="IP" + /> + + <apn carrier="VF AU PXT" + mcc="505" + mnc="07" + apn="live.vodafone.com" + mmsc="http://pxt.vodafone.net.au/pxtsend" + mmsproxy="10.202.2.60" + mmsport="8080" + type="mms" + /> + + <apn carrier="VF Internet" + mcc="505" + mnc="07" + apn="vfinternet.au" + type="default,supl" + /> + + <apn carrier="3Internet" + carrier_id = "1351" + mcc="505" + mnc="12" + apn="3netaccess" + type="default,supl" + /> + + <apn carrier="3" + carrier_id = "1351" + mcc="505" + mnc="12" + apn="3services" + mmsc="http://mmsc.three.net.au:10021/mmsc" + mmsproxy="10.176.57.25" + mmsport="8799" + type="default,supl,mms" + /> + + <apn carrier="Truphone" + carrier_id = "2143" + mcc="505" + mnc="38" + apn="truphone.com" + mmsc="http://mmsc.truphone.com:1981/mm1" + type="default,supl,mms,dun" + /> + + <apn carrier="Telstra IMS" + carrier_id = "1345" + mcc="505" + mnc="71" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Telstra Internet" + carrier_id = "1345" + mcc="505" + mnc="71" + apn="telstra.wap" + type="default,supl" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra MMS" + carrier_id = "1345" + mcc="505" + mnc="71" + apn="telstra.mms" + type="mms" + mmsc="http://mmsc.telstra.com:8002/" + mmsproxy="10.1.1.180" + mmsport="80" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra Tethering" + carrier_id = "1345" + mcc="505" + mnc="71" + apn="telstra.internet" + type="dun" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra HOS" + carrier_id = "1345" + mcc="505" + mnc="71" + apn="hos" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra IMS" + carrier_id = "1345" + mcc="505" + mnc="72" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Telstra Internet" + carrier_id = "1345" + mcc="505" + mnc="72" + apn="telstra.wap" + type="default,supl" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra MMS" + carrier_id = "1345" + mcc="505" + mnc="72" + apn="telstra.mms" + type="mms" + mmsc="http://mmsc.telstra.com:8002/" + mmsproxy="10.1.1.180" + mmsport="80" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra Tethering" + carrier_id = "1345" + mcc="505" + mnc="72" + apn="telstra.internet" + type="dun" + protocol="IPV4V6" + roaming_protocol="IPV4" + /> + + <apn carrier="Telstra HOS" + carrier_id = "1345" + mcc="505" + mnc="72" + apn="hos" + protocol="IPV4" + roaming_protocol="IPV4" + /> + + <apn carrier="VF AU PXT" + carrier_id = "492" + mcc="505" + mnc="88" + apn="live.vodafone.com" + mmsc="http://pxt.vodafone.net.au/pxtsend" + mmsproxy="10.202.2.60" + mmsport="8080" + type="mms" + /> + + <apn carrier="VF Internet" + carrier_id = "492" + mcc="505" + mnc="88" + apn="vfinternet.au" + type="default,supl" + /> + + <apn carrier="Optus Internet" + carrier_id = "30" + mcc="505" + mnc="90" + apn="internet" + type="default,supl" + /> + + <apn carrier="Optus MMS" + carrier_id = "30" + mcc="505" + mnc="90" + apn="mms" + mmsc="http://mmsc.optus.com.au:8002/" + mmsproxy="61.88.190.10" + mmsport="8070" + type="mms" + /> + + <apn carrier="Vodafone Live!" + carrier_id = "1349" + mcc="505" + mnc="99" + apn="live.vodafone.com" + mmsc="http://pxt.vodafone.net.au/pxtsend" + mmsproxy="10.202.2.60" + mmsport="8080" + /> + + <apn carrier="indosatgprs" + carrier_id = "1537" + mcc="510" + mnc="01" + apn="indosatgprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="Indosat MMS" + carrier_id = "1537" + mcc="510" + mnc="01" + apn="indosatmms" + user="indosat" + password="indosat" + authtype="1" + mmsc="http://mmsc.indosat.com" + mmsproxy="10.19.19.19" + mmsport="8080" + type="mms" + /> + + <apn carrier="AXIS-SNS" + carrier_id = "788" + mcc="510" + mnc="08" + apn="AXIS" + authtype="1" + type="default,supl" + /> + + <apn carrier="AXISwap" + carrier_id = "788" + mcc="510" + mnc="08" + apn="AXIS" + user="axis" + password="123456" + proxy="10.8.3.8" + port="8080" + type="default,supl" + authtype="1" + /> + + <apn carrier="AXISmms" + carrier_id = "788" + mcc="510" + mnc="08" + apn="AXISmms" + user="axis" + password="123456" + mmsc="http://mmsc.axis" + mmsproxy="10.8.3.8" + mmsport="8080" + type="mms" + authtype="1" + /> + + <apn carrier="internet" + carrier_id = "787" + mcc="510" + mnc="10" + apn="internet" + type="default,supl" + /> + + <apn carrier="TSEL-WAP" + carrier_id = "787" + mcc="510" + mnc="10" + apn="telkomsel" + user="wap" + password="wap123" + authtype="1" + proxy="10.1.89.130" + port="8000" + type="default,supl" + /> + + <apn carrier="TSEL-MMS" + carrier_id = "787" + mcc="510" + mnc="10" + apn="mms" + user="wap" + password="wap123" + authtype="1" + mmsc="http://mms.telkomsel.com" + mmsproxy="10.1.89.150" + mmsport="8000" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "788" + mcc="510" + mnc="11" + apn="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="XL-MMS" + carrier_id = "788" + mcc="510" + mnc="11" + apn="www.xlmms.net" + user="xlgprs" + password="proxl" + authtype="1" + mmsc="http://mmc.xl.net.id/servlets/mms" + mmsproxy="202.152.240.50" + mmsport="8080" + type="mms" + /> + + <apn carrier="Indosat-SNS" + carrier_id = "789" + mcc="510" + mnc="21" + apn="indosatgprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="Indosat GPRS" + carrier_id = "789" + mcc="510" + mnc="21" + apn="indosatgprs" + user="indosat" + password="indosat" + authtype="1" + proxy="10.19.19.19" + port="8080" + type="default,supl" + /> + + <apn carrier="Indosat MMS" + carrier_id = "789" + mcc="510" + mnc="21" + apn="indosatmms" + user="indosat" + password="indosat" + authtype="1" + mmsc="http://mmsc.indosat.com" + mmsproxy="10.19.19.19" + mmsport="8080" + type="mms" + /> + + <apn carrier="3-SNS" + carrier_id = "1966" + mcc="510" + mnc="89" + apn="3gprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="3GPRS" + carrier_id = "1966" + mcc="510" + mnc="89" + apn="3gprs" + user="3gprs" + password="3gprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="3MMS" + carrier_id = "1966" + mcc="510" + mnc="89" + apn="3mms" + user="3mms" + password="3mms" + authtype="1" + mmsc="http://mms.three.co.id" + mmsproxy="10.4.0.10" + mmsport="3128" + type="mms" + /> + + <apn carrier="Telin" + carrier_id = "2182" + mcc="514" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Timor Telecom" + carrier_id = "2183" + mcc="514" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Viettel Timor-Leste" + carrier_id = "2268" + mcc="514" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="myGlobe Internet" + carrier_id = "1653" + mcc="515" + mnc="02" + apn="internet.globe.com.ph" + type="default,supl" + /> + + <apn carrier="myGlobe INET" + carrier_id = "1653" + mcc="515" + mnc="02" + apn="http.globe.com.ph" + type="default,supl" + /> + + <apn carrier="myGlobe Connect" + carrier_id = "1653" + mcc="515" + mnc="02" + apn="www.globe.com.ph" + proxy="203.177.42.214" + port="8080" + type="default,supl" + /> + + <apn carrier="myGlobe MMS" + carrier_id = "1653" + mcc="515" + mnc="02" + apn="mms.globe.com.ph" + mmsc="http://192.40.100.22:10021/mmsc" + mmsproxy="203.177.42.214" + mmsport="8080" + type="mms" + /> + + <apn carrier="SMARTLTE" + carrier_id = "1654" + mcc="515" + mnc="03" + apn="smartlte" + type="default,supl" + /> + + <apn carrier="SMART INTERNET" + carrier_id = "1654" + mcc="515" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="Smart GPRS" + carrier_id = "1654" + mcc="515" + mnc="03" + apn="Smart1" + proxy="10.102.61.46" + port="8080" + type="default,supl" + /> + + <apn carrier="Smart MMS" + carrier_id = "1654" + mcc="515" + mnc="03" + apn="mms" + mmsc="http://10.102.61.238:8002" + mmsproxy="10.102.61.46" + mmsport="8080" + type="mms" + /> + + <apn carrier="Sun Internet" + carrier_id = "1655" + mcc="515" + mnc="05" + apn="minternet" + type="default,supl" + /> + + <apn carrier="SUN WAP GPRS" + carrier_id = "1655" + mcc="515" + mnc="05" + apn="wap" + proxy="202.138.159.78" + port="8080" + type="default,supl" + /> + + <apn carrier="Sun SBW" + carrier_id = "1655" + mcc="515" + mnc="05" + apn="fbband" + type="default,supl" + /> + + <apn carrier="Sun Streaming" + carrier_id = "1655" + mcc="515" + mnc="05" + apn="minternet" + type="default,supl" + /> + + <apn carrier="SUN MMS" + carrier_id = "1655" + mcc="515" + mnc="05" + apn="mms" + mmsc="http://mmscenter.suncellular.com.ph" + mmsproxy="202.138.159.78" + mmsport="8080" + type="mms" + /> + + <apn carrier="Redinternet" + carrier_id = "2184" + mcc="515" + mnc="18" + apn="redinternet" + type="default,supl" + /> + + <apn carrier="Redmms" + carrier_id = "2184" + mcc="515" + mnc="18" + apn="real.globe.com.ph" + mmsc="http://10.102.61.193:8002/mmsc" + mmsproxy="10.138.3.35" + mmsport="8080" + type="mms" + /> + + <apn carrier="CAT3G INTERNET" + carrier_id = "1096" + mcc="520" + mnc="00" + apn="internet" + type="default,supl" + /> + + <apn carrier="CAT3G MMS" + carrier_id = "1096" + mcc="520" + mnc="00" + apn="catmms" + mmsc="http://mms.cat3g.com:8002/" + mmsproxy="10.4.7.39" + mmsport="8080" + type="mms" + /> + + <apn carrier="TRUE-H INTERNET" + carrier_id = "2336" + mcc="520" + mnc="00" + apn="internet" + user="true" + password="true" + authtype="1" + type="default,supl" + mvno_match_data="01" + mvno_type="gid" + /> + + <apn carrier="TRUE-H MMS" + carrier_id = "2336" + mcc="520" + mnc="00" + apn="hmms" + user="true" + password="true" + authtype="1" + mmsc="http://mms.trueh.com:8002/" + mmsproxy="10.4.7.39" + mmsport="8080" + type="mms" + mvno_match_data="01" + mvno_type="gid" + /> + + <apn carrier="AIS Internet" + carrier_id = "1097" + mcc="520" + mnc="01" + apn="internet" + authtype="0" + type="default,supl" + /> + + <apn carrier="AIS MMS" + carrier_id = "1097" + mcc="520" + mnc="01" + apn="multimedia" + mmsc="http://mms.mobilelife.co.th" + mmsproxy="203.170.229.34" + mmsport="8080" + type="mms" + /> + + <apn carrier="AIS Internet" + carrier_id = "1098" + mcc="520" + mnc="03" + apn="internet" + authtype="0" + type="default,supl" + /> + + <apn carrier="AIS MMS" + carrier_id = "1098" + mcc="520" + mnc="03" + apn="multimedia" + mmsc="http://mms.mobilelife.co.th" + mmsproxy="203.170.229.34" + mmsport="8080" + type="mms" + /> + + <apn carrier="TRUE-H INTERNET" + carrier_id = "1997" + mcc="520" + mnc="04" + apn="internet" + user="true" + password="true" + authtype="1" + type="default,supl" + /> + + <apn carrier="TRUE-H MMS" + carrier_id = "1997" + mcc="520" + mnc="04" + apn="hmms" + user="true" + password="true" + authtype="1" + mmsc="http://mms.trueh.com:8002/" + mmsproxy="10.4.7.39" + mmsport="8080" + type="mms" + /> + + <apn carrier="dtac Internet" + carrier_id = "1897" + mcc="520" + mnc="05" + apn="www.dtac.co.th" + type="default,supl" + /> + + <apn carrier="dtac MMS" + carrier_id = "1897" + mcc="520" + mnc="05" + apn="mms" + mmsc="http://mms2.dtac.co.th:8002/" + mmsproxy="10.10.10.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="TOT 3G Internet" + carrier_id = "1723" + mcc="520" + mnc="15" + apn="internet" + type="default,supl" + /> + + <apn carrier="TOT 3G MMS" + carrier_id = "1723" + mcc="520" + mnc="15" + apn="mms" + mmsc="http://mms.tot3g.net:8002" + mmsproxy="192.168.0.72" + mmsport="8080" + type="mms" + /> + + <apn carrier="dtac MMS" + carrier_id = "1896" + mcc="520" + mnc="18" + apn="mms" + mmsc="http://mms.dtac.co.th:8002/" + mmsproxy="203.155.200.133" + mmsport="8080" + type="mms" + /> + + <apn carrier="dtac Internet" + carrier_id = "1896" + mcc="520" + mnc="18" + apn="www.dtac.co.th" + type="default,supl" + /> + + <apn carrier="TRUE INTERNET" + carrier_id = "1898" + mcc="520" + mnc="99" + apn="internet" + user="true" + password="true" + authtype="1" + type="default,supl" + /> + + <apn carrier="TRUE MMS" + carrier_id = "1898" + mcc="520" + mnc="99" + apn="hmms" + user="true" + password="true" + authtype="1" + mmsc="http://mms.truelife.com:8002/" + mmsproxy="10.4.7.39" + mmsport="8080" + type="mms" + /> + + <apn carrier="SingTel (PostPaid)" + carrier_id = "31" + mcc="525" + mnc="01" + apn="e-ideas" + mmsproxy="165.21.42.84" + mmsport="8080" + mmsc="http://mms.singtel.com:10021/mmsc" + type="default,supl,mms" + /> + + <apn carrier="SingTel (PrePaid)" + carrier_id = "31" + mcc="525" + mnc="01" + apn="hicard" + mmsproxy="165.21.42.84" + mmsport="8080" + mmsc="http://mms.singtel.com:10021/mmsc" + type="default,supl,mms" + /> + + <apn carrier="SingTel (PostPaid)" + carrier_id = "31" + mcc="525" + mnc="02" + apn="e-ideas" + mmsproxy="165.21.42.84" + mmsport="8080" + mmsc="http://mms.singtel.com:10021/mmsc" + type="default,supl,mms" + /> + + <apn carrier="SingTel (PrePaid)" + carrier_id = "31" + mcc="525" + mnc="02" + apn="hicard" + mmsproxy="165.21.42.84" + mmsport="8080" + mmsc="http://mms.singtel.com:10021/mmsc" + type="default,supl,mms" + /> + + <apn carrier="Sunsurf Mobile" + carrier_id = "1706" + mcc="525" + mnc="03" + apn="sunsurf" + type="default,supl" + /> + + <apn carrier="M1 MMS(3G)" + carrier_id = "1706" + mcc="525" + mnc="03" + apn="miworld" + user="65" + password="user123" + mmsc="http://mmsgw:8002" + mmsproxy="172.16.14.10" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Sunsurf Mobile" + carrier_id = "2238" + mcc="525" + mnc="04" + apn="sunsurf" + type="default,supl" + /> + + <apn carrier="M1 MMS(3G)" + carrier_id = "2238" + mcc="525" + mnc="04" + apn="miworld" + user="65" + password="user123" + authtype="1" + mmsc="http://mmsgw:8002" + mmsproxy="172.16.14.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="SH Data Postpaid" + carrier_id = "1707" + mcc="525" + mnc="05" + apn="shwap" + type="default,supl" + /> + + <apn carrier="SH MMS Postpaid" + carrier_id = "1707" + mcc="525" + mnc="05" + apn="shmms" + mmsc="http://mms.starhubgee.com.sg:8002/" + mmsproxy="10.12.1.80" + mmsport="80" + type="mms" + /> + + <apn carrier="B-Mobile" + carrier_id = "2350" + mcc="528" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="DSTCom" + carrier_id = "1379" + mcc="528" + mnc="11" + apn="default" + type="default,supl" + /> + + <apn carrier="VFNZ Gateway" + carrier_id = "2364" + mcc="530" + mnc="01" + apn="live.vodafone.com" + mmsc="http://pxt.vodafone.net.nz/pxtsend" + mmsproxy="172.30.38.3" + mmsport="8080" + type="mms" + /> + + <apn carrier="VFNZ Internet" + carrier_id = "2364" + mcc="530" + mnc="01" + apn="vodafone" + type="default,supl" + /> + + <apn carrier="Data" + carrier_id = "968" + mcc="530" + mnc="05" + apn="Internet" + type="default,supl" + /> + + <apn carrier="Content" + carrier_id = "968" + mcc="530" + mnc="05" + apn="Internet" + proxy="210.55.11.73" + port="80" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "968" + mcc="530" + mnc="05" + apn="Internet" + mmsc="http://lsmmsc.xtra.co.nz" + mmsproxy="210.55.11.73" + mmsport="80" + type="mms" + /> + + <apn carrier="Default" + carrier_id = "2105" + mcc="530" + mnc="05" + apn="wapaccess.co.nz" + type="default,supl" + mvno_match_data="Skinny" + mvno_type="spn" + /> + + <apn carrier="Content" + carrier_id = "2105" + mcc="530" + mnc="05" + apn="wapaccess.co.nz" + proxy="210.55.11.73" + port="80" + type="default,supl" + mvno_match_data="Skinny" + mvno_type="spn" + /> + + <apn carrier="Data" + carrier_id = "2105" + mcc="530" + mnc="05" + apn="wapaccess.co.nz" + type="default,supl" + mvno_match_data="Skinny" + mvno_type="spn" + /> + + <apn carrier="MMS" + carrier_id = "2105" + mcc="530" + mnc="05" + apn="wapaccess.co.nz" + mmsc="http://mms.mmsaccess.co.nz" + mmsproxy="210.55.11.73" + mmsport="80" + type="mms" + mvno_match_data="Skinny" + mvno_type="spn" + /> + + <apn carrier="2Degrees Internet" + carrier_id = "969" + mcc="530" + mnc="24" + apn="internet" + type="default,supl" + /> + + <apn carrier="2Degrees MMS" + carrier_id = "969" + mcc="530" + mnc="24" + apn="mms" + mmsc="http://mms.2degreesmobile.net.nz:48090" + mmsproxy="118.148.1.118" + mmsport="8080" + type="mms" + /> + + <apn carrier="Digicel" + mcc="536" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="BeMobile" + carrier_id = "1649" + mcc="537" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="PNG WAP" + carrier_id = "1651" + mcc="537" + mnc="03" + apn="wap.digicelpng.com" + proxy="10.149.83.116" + port="8080" + type="default,supl" + /> + + <apn carrier="PNG WEB" + carrier_id = "1651" + mcc="537" + mnc="03" + apn="internet.digicelpng.com" + type="default,supl" + /> + + <apn carrier="Papua New Guinea:Digicel:Modem" + carrier_id = "1651" + mcc="537" + mnc="03" + apn="wap.digicel.com.pg" + type="dun" + authtype="1" + mmsc="http://wapdigicel.com" + proxy="10.149.122.12" + port="8080" + /> + + <apn carrier="PNG MMS" + carrier_id = "1651" + mcc="537" + mnc="03" + apn="wap.digicelpng.com" + mmsc="http://mms.digicelpng.com:8990" + mmsproxy="10.149.83.116" + mmsport="8080" + type="mms" + /> + + <apn carrier="EMnify" + carrier_id = "2326" + mcc="537" + mnc="03" + apn="em" + mvno_match_data="5370309" + mvno_type="imsi" + type="default,supl" + /> + + <apn carrier="U-Call" + carrier_id = "1733" + mcc="539" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Shoreline Communication" + carrier_id = "1734" + mcc="539" + mnc="43" + apn="default" + type="default,supl" + /> + + <apn carrier="Digicel" + carrier_id = "2220" + mcc="539" + mnc="88" + apn="default" + type="default,supl" + /> + + <apn carrier="Tonga:Digicel:Modem" + carrier_id = "2220" + mcc="539" + mnc="88" + apn="wap" + type="dun" + authtype="1" + mmsc="http://wapdigicel.com" + proxy="172.16.7.12" + port="8080" + /> + + <apn carrier="Tonga:Digicel:Mms" + carrier_id = "2220" + mcc="539" + mnc="88" + apn="wap" + type="mms" + authtype="1" + mmsproxy="172.16.7.12" + mmsc="http://mms.digicelgroup.com" + mmsport="9201" + /> + + <apn carrier="BREEZE" + carrier_id = "2185" + mcc="540" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="BeMobile" + carrier_id = "2123" + mcc="540" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="AIL" + carrier_id = "2239" + mcc="541" + mnc="00" + apn="default" + type="default,supl" + /> + + <apn carrier="SMILE" + carrier_id = "1301" + mcc="541" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Digicel" + carrier_id = "2219" + mcc="541" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Vanatu:Digicel:Modem" + carrier_id = "2219" + mcc="541" + mnc="05" + apn="wap" + type="dun" + authtype="1" + mmsc="http://wapdigicel.com" + proxy="172.16.7.12" + port="8080" + /> + + <apn carrier="Vanatu:Digicel:Mms" + carrier_id = "2219" + mcc="541" + mnc="05" + apn="wap" + type="mms" + authtype="1" + mmsproxy="172.16.7.12" + mmsc="http://mms.digicelgroup.com" + mmsport="9201" + /> + + <apn carrier="Vodafone" + carrier_id = "1481" + mcc="542" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Digicel" + carrier_id = "2186" + mcc="542" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Fiji:Digicel:Modem" + carrier_id = "2186" + mcc="542" + mnc="02" + apn="wap" + type="dun" + authtype="1" + mmsc="http://wapdigicel.com" + proxy="172.16.7.12" + port="8080" + /> + + <apn carrier="Fiji:Digicel:Mms" + carrier_id = "2186" + mcc="542" + mnc="02" + apn="wap" + type="mms" + authtype="1" + mmsproxy="172.16.7.12" + mmsc="http://mms.digicelgroup.com" + mmsport="9201" + /> + + <apn carrier="Bluesky" + carrier_id = "1957" + mcc="544" + mnc="11" + apn="default" + type="default,supl" + /> + + <apn carrier="Kiribati - TSKL" + carrier_id = "2240" + mcc="545" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Kiribati - Frigate Net" + carrier_id = "2187" + mcc="545" + mnc="09" + apn="default" + type="default,supl" + /> + + <apn carrier="Mobilis" + carrier_id = "943" + mcc="546" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Vini" + carrier_id = "1648" + mcc="547" + mnc="20" + apn="default" + type="default,supl" + /> + + <apn carrier="Telecom Cook" + carrier_id = "1426" + mcc="548" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Digicel" + carrier_id = "1302" + mcc="549" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Bluesky" + carrier_id = "1876" + mcc="549" + mnc="27" + apn="default" + type="default,supl" + /> + + <apn carrier="FSMTC" + carrier_id = "1482" + mcc="550" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="MINTA" + mcc="551" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="PNCC" + carrier_id = "1671" + mcc="552" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Palau Mobile" + carrier_id = "2188" + mcc="552" + mnc="80" + apn="default" + type="default,supl" + /> + + <apn carrier="Mobinil Web" + carrier_id = "675" + mcc="602" + mnc="01" + apn="mobinilweb" + type="default,supl" + /> + + <apn carrier="Mobinil WAP" + carrier_id = "675" + mcc="602" + mnc="01" + apn="mobinilwap" + proxy="62.241.155.45" + port="8080" + type="default,supl" + /> + + <apn carrier="Mobinil MMS" + carrier_id = "675" + mcc="602" + mnc="01" + apn="mobinilmms" + mmsc="http://10.7.13.24:8002" + mmsproxy="62.241.155.45" + mmsport="8080" + type="mms" + /> + + <apn carrier="vodafone internet" + carrier_id = "2380" + mcc="602" + mnc="02" + apn="internet.vodafone.net" + user="internet" + password="internet" + authtype="3" + type="default,supl" + /> + + <apn carrier="Vodafone WAP" + carrier_id = "2380" + mcc="602" + mnc="02" + apn="wap.vodafone.com.eg" + user="wap" + password="wap" + authtype="3" + proxy="163.121.178.2" + port="8080" + type="default,supl" + /> + + <apn carrier="Vodafone MMS" + carrier_id = "2380" + mcc="602" + mnc="02" + apn="mms.vodafone.com.eg" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.vodafone.com.eg/servlets/mms" + mmsproxy="163.121.178.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Etisalat WAP" + carrier_id = "1968" + mcc="602" + mnc="03" + apn="etisalat" + proxy="10.71.130.29" + port="8080" + type="default,supl" + /> + + <apn carrier="Etisalat MMS" + carrier_id = "1968" + mcc="602" + mnc="03" + apn="etisalat" + mmsc="http://10.71.131.7:38090" + mmsproxy="10.71.130.29" + mmsport="8080" + type="mms" + /> + + <apn carrier="mobilis wap" + carrier_id = "1470" + mcc="603" + mnc="01" + apn="wap" + proxy="172.25.49.2" + port="8080" + user="wap" + password="wap" + authtype="1" + type="default,supl" + /> + + <apn carrier="Mobilis internet" + carrier_id = "1470" + mcc="603" + mnc="01" + apn="internet" + user="internet" + password="internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Mobilis mms" + carrier_id = "1470" + mcc="603" + mnc="01" + apn="mms" + user="mms" + password="mms" + authtype="1" + mmsc="http://172.25.49.9/servlets/mms" + mmsproxy="172.25.49.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="djezzy.internet" + carrier_id = "1471" + mcc="603" + mnc="02" + apn="djezzy.internet" + type="default,supl" + /> + + <apn carrier="djezzy.mms" + carrier_id = "1471" + mcc="603" + mnc="02" + apn="djezzy.mms" + user="mms" + password="mms" + mmsc="http://172.24.97.152:6021/mmsc" + mmsproxy="172.24.97.158" + mmsport="8799" + type="mms" + /> + + <apn carrier="Ooredoo internet" + carrier_id = "1977" + mcc="603" + mnc="03" + apn="internet" + type="default,supl" + authtype="1" + /> + + <apn carrier="Ooredoo mms" + carrier_id = "1977" + mcc="603" + mnc="03" + apn="ooredoomms" + user="mms" + password="mms" + mmsc="http://10.10.111.1" + mmsproxy="192.168.52.3" + mmsport="3128" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "902" + mcc="604" + mnc="00" + apn="internet.orange.ma" + authtype="1" + type="default,supl" + /> + + <apn carrier="Imedia" + carrier_id = "902" + mcc="604" + mnc="00" + apn="wap.meditel.ma" + proxy="10.8.8.8" + port="8080" + user="MEDIWAP" + password="MEDIWAP" + authtype="1" + type="default,supl" + /> + + <apn carrier="GPRS MMS" + carrier_id = "902" + mcc="604" + mnc="00" + apn="mms.meditel.ma" + user="MEDIMMS" + password="MEDIMMS" + authtype="1" + mmsc="http://mms.meditel.ma:8088/mms" + mmsproxy="10.8.8.9" + mmsport="8080" + type="mms" + /> + + <apn carrier="MobileZone" + carrier_id = "903" + mcc="604" + mnc="01" + apn="wap.iamgprs.ma" + proxy="212.217.54.133" + port="8080" + type="default,supl" + /> + + <apn carrier="Internet Mobile" + carrier_id = "903" + mcc="604" + mnc="01" + apn="www.iamgprs1.ma" + type="default,supl" + /> + + <apn carrier="MMS IAM" + carrier_id = "903" + mcc="604" + mnc="01" + apn="mmsiam" + mmsc="http://mms:8002/" + mmsproxy="10.16.35.50" + mmsport="8080" + type="mms" + /> + + <apn carrier="WEB" + carrier_id = "1985" + mcc="604" + mnc="02" + apn="www.wana.ma" + type="default,supl" + /> + + <apn carrier="WAP" + carrier_id = "1985" + mcc="604" + mnc="02" + apn="www.wana.ma" + proxy="10.86.0.10" + port="8080" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1985" + mcc="604" + mnc="02" + apn="mms.wana.ma" + mmsc="http://mms.wana.ma:38090" + mmsproxy="10.86.0.10" + mmsport="8080" + type="mms" + /> + + <apn carrier="weborange" + carrier_id = "1936" + mcc="605" + mnc="01" + apn="weborange" + type="default,supl" + /> + + <apn carrier="MMS Orange" + carrier_id = "1936" + mcc="605" + mnc="01" + apn="mms.otun" + mmsc="http://mms.orange.tn" + mmsproxy="10.12.1.52" + mmsport="8080" + type="mms" + /> + + <apn carrier="Internet" + carrier_id = "1731" + mcc="605" + mnc="02" + apn="internet.tn" + type="default,supl" + /> + + <apn carrier="Internet Portail" + carrier_id = "1731" + mcc="605" + mnc="02" + apn="gprs.tn" + user="gprs" + password="gprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="Tunisie Telecom MMS" + carrier_id = "1731" + mcc="605" + mnc="02" + apn="mms.tn" + user="mms@tt1" + password="mms" + authtype="1" + mmsc="http://192.168.0.3:19090/was" + mmsproxy="192.168.0.2" + mmsport="8080" + type="mms" + /> + + <apn carrier="Ooredoo TN Internet" + carrier_id = "1732" + mcc="605" + mnc="03" + apn="internet.ooredoo.tn" + type="default" + /> + + <apn carrier="Ooredoo TN MMS" + carrier_id = "1732" + mcc="605" + mnc="03" + apn="mms.ooredoo.tn" + mmsc="http://mmsc.ooredoo.tn" + mmsproxy="10.3.2.100" + mmsport="80" + type="mms" + /> + + <apn carrier="Libyana" + carrier_id = "1973" + mcc="606" + mnc="00" + apn="default" + type="default,supl" + /> + + <apn carrier="Libyana MMS" + carrier_id = "1973" + mcc="606" + mnc="00" + apn="mms" + type="mms" + authtype="0" + mmsproxy="192.168.8.148" + mmsc="http://62.240.62.180:80" + mmsport="8000" + /> + + <apn carrier="Madar" + carrier_id = "2006" + mcc="606" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Al-Jeel Phone" + carrier_id = "2189" + mcc="606" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Libya Phone" + carrier_id = "2348" + mcc="606" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Hatef Libya" + carrier_id = "2190" + mcc="606" + mnc="06" + apn="default" + type="default,supl" + /> + + <apn carrier="Gamcel" + carrier_id = "736" + mcc="607" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Africel" + carrier_id = "737" + mcc="607" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Comium" + carrier_id = "738" + mcc="607" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="QCell" + carrier_id = "2191" + mcc="607" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange MMS SN" + carrier_id = "1721" + mcc="608" + mnc="01" + apn="mms" + user="mms" + password="mms" + mmsc="http://mmsalize/servlets/mms" + mmsproxy="172.16.30.9" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Wap SN" + carrier_id = "1721" + mcc="608" + mnc="01" + apn="wap" + user="wap" + password="wap" + proxy="172.16.30.9" + port="8080" + type="default" + /> + + <apn carrier="Orange Web SN" + carrier_id = "1721" + mcc="608" + mnc="01" + apn="internet" + user="internet" + password="internet" + type="default" + /> + + <apn carrier="Tigo Internet SN" + carrier_id = "1722" + mcc="608" + mnc="02" + apn="web.sentel.com" + type="default,supl" + /> + + <apn carrier="Expresso Internet SN" + carrier_id = "2192" + mcc="608" + mnc="03" + apn="expresso" + user="wap" + password="wap" + proxy="10.71.123.69" + port="8080" + type="default" + /> + + <apn carrier="Mattel" + carrier_id = "1616" + mcc="609" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Chinguitel" + carrier_id = "1617" + mcc="609" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Mauritel" + carrier_id = "1618" + mcc="609" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange 3G/4G" + carrier_id = "2034" + mcc="610" + mnc="02" + apn="internet" + authtype="1" + user="internet" + password="internet" + type="default" + /> + + <apn carrier="Orange ML MMS" + carrier_id = "2034" + mcc="610" + mnc="02" + apn="mms" + user="mms" + password="mms" + mmsc="http://10.109.6.2/servlets/mms" + mmsproxy="10.109.4.35" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange Wap ML" + carrier_id = "2034" + mcc="610" + mnc="02" + apn="wap" + user="wap" + password="wap" + proxy="10.109.4.35" + port="8080" + type="default" + /> + + <apn carrier="Orange S.A." + carrier_id = "739" + mcc="611" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Sotelgui" + carrier_id = "740" + mcc="611" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Telecel Guinee" + carrier_id = "2193" + mcc="611" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "2225" + mcc="611" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Cellcom" + carrier_id = "741" + mcc="611" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Moov Internet CI" + carrier_id = "1420" + mcc="612" + mnc="02" + apn="moov" + user="web" + password="web" + proxy="10.172.11.17" + port="8080" + type="default" + /> + + <apn carrier="Oweb" + carrier_id = "1421" + mcc="612" + mnc="03" + apn="orangeciweb" + user="web" + password="web" + authtype="1" + type="default" + /> + + <apn carrier="OWORLD CI" + carrier_id = "1421" + mcc="612" + mnc="03" + apn="orangeciwap" + user="wap" + password="wap" + proxy="172.20.4.33" + port="8080" + type="default" + /> + + <apn carrier="Omms CI" + carrier_id = "1421" + mcc="612" + mnc="03" + apn="orangecimms" + user="mms" + password="mms" + mmsc="http://172.20.6.1/servlets/mms" + mmsproxy="172.20.4.33" + mmsport="8080" + type="mms" + /> + + <apn carrier="Koz Internet CI" + carrier_id = "1422" + mcc="612" + mnc="04" + apn="gprs.koz.ci" + user="web" + password="web" + proxy="10.20.3.10" + port="8080" + type="default" + /> + + <apn carrier="MTN Internet CI" + carrier_id = "1423" + mcc="612" + mnc="05" + apn="web.mtn.ci" + user="vide" + password="vide" + type="default" + /> + + <apn carrier="Telmob" + carrier_id = "1946" + mcc="613" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1368" + mcc="613" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Telecel Faso" + carrier_id = "1369" + mcc="613" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange MMS" + apn="orange.mms" + user="orange" + password="orange" + mmsc="http://10.10.10.35:38090/was" + mmsproxy="10.10.10.36" + mmsport="8080" + carrier_id = "1943" + mcc="614" + mnc="04" + type="mms" + /> + + <apn carrier="Orange Internet" + apn="orange.ne" + carrier_id = "1943" + mcc="614" + mnc="04" + type="default" + /> + + <apn carrier="Togo Cell" + carrier_id = "1095" + mcc="615" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Moov" + carrier_id = "1947" + mcc="615" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Libercom" + carrier_id = "1376" + mcc="616" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Moov" + carrier_id = "1377" + mcc="616" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "1378" + mcc="616" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="BBCOM" + carrier_id = "1944" + mcc="616" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Glo" + carrier_id = "1945" + mcc="616" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange MMS" + apn="orangemms" + user="mmsc" + password="mmsc" + mmsc="http://10.2.1.20:8514" + mmsproxy="10.2.1.20" + mmsport="8080" + carrier_id = "1621" + mcc="617" + mnc="01" + type="mms" + /> + + <apn carrier="Orange Internet" + apn="orange" + carrier_id = "1621" + mcc="617" + mnc="01" + type="default" + /> + + <apn carrier="Lonestar Cell" + carrier_id = "2194" + mcc="618" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Libercell" + carrier_id = "2195" + mcc="618" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Comium" + carrier_id = "1601" + mcc="618" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange" + carrier_id = "2035" + mcc="618" + mnc="07" + apn="Orange" + type="default,supl" + /> + + <apn carrier="LIBTELCO" + carrier_id = "2196" + mcc="618" + mnc="20" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1716" + mcc="619" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Tigo" + carrier_id = "1717" + mcc="619" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Africell" + carrier_id = "1718" + mcc="619" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Comium" + carrier_id = "1074" + mcc="619" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Africell" + carrier_id = "1075" + mcc="619" + mnc="05" + apn="default" + type="default,supl" + /> + + <apn carrier="Mobitel" + carrier_id = "1076" + mcc="619" + mnc="25" + apn="default" + type="default,supl" + /> + + <apn carrier="Glo" + mcc="620" + mnc="0" + apn="glowap" + authtype="0" + type="default,supl,agps,fota,dun" + /> + + <apn carrier="Glo mms" + mcc="620" + mnc="0" + apn="glo mms" + authtype="0" + mmsc="http://mms.gloworld.com/mms" + mmsproxy="10.161.85.4" + mmsport="8799" + type="mms" + /> + + <apn carrier="MTN Internet GH" + apn="internet" + carrier_id = "1515" + mcc="620" + mnc="01" + type="default" + /> + + <apn carrier="MTN MMS" + carrier_id = "1515" + mcc="620" + mnc="01" + apn="mtn mms" + type="mms" + authtype="0" + mmsproxy="172.17.3.7" + mmsc="http://172.17.3.7" + mmsport="8080" + /> + + <apn carrier="Vodafone Internet GH" + apn="browse" + carrier_id = "2383" + mcc="620" + mnc="02" + type="default" + /> + + <apn carrier="Vodafone_mms" + carrier_id = "2383" + mcc="620" + mnc="02" + apn="mms" + type="mms" + authtype="0" + mmsproxy="172.24.97.1" + mmsc="http://mms.vodaphone.com.gh/mms" + mmsport="9201" + /> + + <apn carrier="Tigo Internet GH" + apn="web.tigo.com.gh" + carrier_id = "2108" + mcc="620" + mnc="03" + type="default" + /> + + <apn carrier="Tigo mms" + carrier_id = "2108" + mcc="620" + mnc="03" + apn="mms.tigo.com.gh" + type="mms" + authtype="0" + mmsproxy="10.4.1.7" + mmsc="http://mms/" + mmsport="8080" + /> + + <apn carrier="Airtel Internet GH" + apn="wap" + carrier_id = "2108" + mcc="620" + mnc="06" + proxy="10.93.85.88" + port="9201" + type="default" + /> + + <apn carrier="Airtel mms" + carrier_id = "2108" + mcc="620" + mnc="06" + apn="mms/airtel mms" + type="mms" + authtype="0" + mmsproxy="100.1.201.172" + mmsc="http://100.1.201.171:10021/mmsc" + mmsport="8799" + /> + + <apn carrier="Glo Internet GH" + apn="glowap" + carrier_id = "2222" + mcc="620" + mnc="07" + user="glo" + password="glo" + authtype="1" + proxy="10.161.85.4" + port="8799" + type="default" + /> + + <apn carrier="Airtel Internet" + carrier_id = "1638" + mcc="621" + mnc="20" + apn="internet.ng.zain.com" + user="internet" + password="internet" + authtype="1" + port="8080" + type="default,supl" + /> + + <apn carrier="Airtel MMS" + carrier_id = "1638" + mcc="621" + mnc="20" + apn="mms.ng.zain.com" + user="mms" + password="mms" + authtype="1" + mmsc="http://10.210.3.239:9800/mm1" + mmsproxy="172.18.254.5" + type="mms" + /> + + <apn carrier="Airtel WAP" + carrier_id = "1638" + mcc="621" + mnc="20" + apn="wap.ng.zain.com" + user="wap" + password="wap" + authtype="1" + proxy="172.18.254.5" + port="8080" + type="default,supl" + /> + + <apn carrier="MTN-WEB" + carrier_id = "1639" + mcc="621" + mnc="30" + apn="internet" + user="web" + password="web" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTN ACESS" + carrier_id = "1639" + mcc="621" + mnc="30" + apn="web.gprs.mtnnigeria.net" + user="web" + password="web" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTN MMS" + carrier_id = "1639" + mcc="621" + mnc="30" + apn="web.gprs.mtnnigeria.net" + mmsc="http://10.199.212.8/servlets/mms" + mmsproxy="10.199.212.2" + type="mms" + /> + + <apn carrier="Glo Direct" + carrier_id = "2115" + mcc="621" + mnc="50" + apn="glosecure" + user="gprs" + password="gprs" + authtype="1" + type="default,supl" + /> + + <apn carrier="Glo MMS" + carrier_id = "2115" + mcc="621" + mnc="50" + apn="glomms" + user="mms" + password="mms" + authtype="1" + mmsc="http://mms.gloworld.com/mmsc" + mmsproxy="10.100.82.4" + mmsport="8080" + type="mms" + /> + + <apn carrier="etisalat WAP" + carrier_id = "1979" + mcc="621" + mnc="60" + apn="etisalat" + proxy="10.71.170.5" + port="8080" + type="default,supl" + /> + + <apn carrier="etisalat MMS" + carrier_id = "1979" + mcc="621" + mnc="60" + apn="etisalat" + mmsc="http://10.71.170.30:38090/was" + type="mms" + /> + + <apn carrier="Airtel" + carrier_id = "1093" + mcc="622" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Tawali" + carrier_id = "1094" + mcc="622" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Tigo" + carrier_id = "2227" + mcc="622" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Salam" + carrier_id = "2197" + mcc="622" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="CTP" + carrier_id = "1408" + mcc="623" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="TC" + carrier_id = "1409" + mcc="623" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Internet browsing" + carrier_id = "1410" + mcc="623" + mnc="03" + apn="orangeca3g" + type="default,supl" + /> + + <apn carrier="Nationlink" + carrier_id = "2198" + mcc="623" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="CVMOVEL" + carrier_id = "1445" + mcc="625" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="T+" + carrier_id = "1446" + mcc="625" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="CSTmovel" + carrier_id = "1086" + mcc="626" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange GQ" + carrier_id = "746" + mcc="627" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange GQ MMS" + carrier_id = "746" + mcc="627" + mnc="01" + apn="orangemms" + type="mms" + user="mms" + password="mms" + authtype="0" + mmsproxy="192.168.17.2" + mmsc="http://192.168.17.34/servlets/mms" + mmsport="8080" + /> + + <apn carrier="Hits GQ" + carrier_id = "2199" + mcc="627" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Libertis" + carrier_id = "1488" + mcc="628" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Moov" + carrier_id = "1489" + mcc="628" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1490" + mcc="628" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Azur" + carrier_id = "2200" + mcc="628" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1411" + mcc="629" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Libertis Telecom" + carrier_id = "1412" + mcc="629" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="Vodacom Internet CD" + carrier_id = "1405" + mcc="630" + mnc="01" + apn="vodanet" + port="8080" + type="default" + /> + + <apn carrier="Vodacom MMS" + carrier_id = "1405" + mcc="630" + mnc="01" + apn="vodalive" + type="mms" + authtype="0" + mmsproxy="172.24.97.1" + mmsc="http://172.24.97.1/mmsc" + mmsport="8080" + /> + + <apn carrier="Tigo Internet CD" + carrier_id = "2036" + mcc="630" + mnc="89" + apn="tigo.web" + type="default" + /> + + <apn carrier="UNITEL" + carrier_id = "1334" + mcc="631" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="MOVICEL" + carrier_id = "2201" + mcc="631" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Areeba" + carrier_id = "1524" + mcc="632" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange Bissau" + carrier_id = "1948" + mcc="632" + mnc="03" + apn="4Gogb" + type="default,supl" + /> + + <apn carrier="Guinetel" + carrier_id = "2241" + mcc="632" + mnc="07" + apn="default" + type="default,supl" + /> + + <apn carrier="Cable & Wireless" + carrier_id = "1685" + mcc="633" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Mediatech International" + carrier_id = "1686" + mcc="633" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1687" + mcc="633" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="Zain SD" + carrier_id = "1688" + mcc="634" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "1689" + mcc="634" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Sudani One" + carrier_id = "2202" + mcc="634" + mnc="07" + apn="default" + type="default,supl" + /> + + <apn carrier="Privet Network" + carrier_id = "2242" + mcc="634" + mnc="09" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "1682" + mcc="635" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="Rwandatel" + carrier_id = "2243" + mcc="635" + mnc="12" + apn="default" + type="default,supl" + /> + + <apn carrier="Tigo" + carrier_id = "2203" + mcc="635" + mnc="13" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "2204" + mcc="635" + mnc="14" + apn="default" + type="default,supl" + /> + + <apn carrier="ETH-MTN" + carrier_id = "681" + mcc="636" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Telesom" + carrier_id = "2205" + mcc="637" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Somafone" + carrier_id = "2244" + mcc="637" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Nationlink" + carrier_id = "2206" + mcc="637" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="Hormuud" + carrier_id = "2245" + mcc="637" + mnc="25" + apn="default" + type="default,supl" + /> + + <apn carrier="Golis" + carrier_id = "1082" + mcc="637" + mnc="30" + apn="default" + type="default,supl" + /> + + <apn carrier="Unittel" + carrier_id = "2246" + mcc="637" + mnc="57" + apn="default" + type="default,supl" + /> + + <apn carrier="Nationlink Telecom" + mcc="637" + mnc="60" + apn="default" + type="default,supl" + /> + + <apn carrier="Somtel" + carrier_id = "2207" + mcc="637" + mnc="71" + apn="default" + type="default,supl" + /> + + <apn carrier="Telcom" + carrier_id = "2208" + mcc="637" + mnc="82" + apn="default" + type="default,supl" + /> + + <apn carrier="Evatis" + carrier_id = "1462" + mcc="638" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="safaricom GPRS" + carrier_id = "865" + mcc="639" + mnc="02" + apn="safaricom" + user="saf" + password="data" + authtype="1" + proxy="172.22.2.38" + port="8080" + type="default,supl" + /> + + <apn carrier="safaricom mms" + carrier_id = "865" + mcc="639" + mnc="02" + apn="safaricom" + user="saf" + password="data" + authtype="1" + mmsproxy="172.22.2.38" + mmsport="8080" + mmsc="http://mms.gprs.safaricom.com" + type="mms" + /> + + + <apn carrier="Airtel Internet" + carrier_id = "866" + mcc="639" + mnc="03" + apn="internet" + type="default,supl" + /> + + <apn carrier="Airtel mms" + carrier_id = "866" + mcc="639" + mnc="03" + apn="mms" + mmsc="http://mms.ke.airtel.com:8002" + mmsproxy="172.30.9.8" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier="Airtel" + carrier_id = "866" + mcc="639" + mnc="03" + apn="ke.celtel.com" + type="default,supl" + /> + + <apn carrier="mms" + carrier_id = "866" + mcc="639" + mnc="03" + apn="ke.celtel.com" + mmsproxy="172.30.8.50" + mmsport="8080" + mmsc="http://mms.ke.celtel.com/servlets/mms" + type="mms" + /> + + <apn carrier="Yu Internet" + carrier_id = "2209" + mcc="639" + mnc="05" + apn="Internet" + proxy="10.4.16.6" + port="8080" + mmsproxy="10.4.16.6" + mmsport="8080" + mmsc="http://10.4.16.22/servlets/mms" + type="default,supl,mms" + /> + + <apn carrier="Yu WAP" + carrier_id = "2209" + mcc="639" + mnc="05" + apn="Yu internet" + type="default,supl" + /> + + <apn carrier="Yu mms" + carrier_id = "2209" + mcc="639" + mnc="05" + apn="Yu" + mmsproxy="10.4.16.6" + mmsport="8080" + mmsc="http://10.4.16.22/servlets/mms" + type="mms" + /> + + <apn carrier="Orange Internet" + carrier_id = "2210" + mcc="639" + mnc="07" + apn="bew.orange.co.ke" + type="default,supl" + /> + + <apn carrier="Orange MMS" + carrier_id = "2210" + mcc="639" + mnc="07" + apn="mms.orange.co.ke" + mmsproxy="10.36.17.130" + mmsport="8080" + mmsc="http://10.36.16.5/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Vodacom WAP" + carrier_id = "1744" + mcc="640" + mnc="04" + apn="Wap" + proxy="10.154.0.8" + port="9401" + type="default,supl" + mvno_match_data="VodaCom Tanzania" + mvno_type="spn" + /> + + <apn carrier="Vodacom MMS" + carrier_id = "1744" + mcc="640" + mnc="04" + apn="mms" + mmsc="http://10.154.0.12/mms/" + type="mms" + mvno_match_data="VodaCom Tanzania" + mvno_type="spn" + /> + + <apn carrier="Airtel Internet UG" + apn="internet" + carrier_id = "1753" + mcc="641" + mnc="01" + type="default" + /> + + <apn carrier="MTN-WEB" + apn="internet" + carrier_id = "1754" + mcc="641" + mnc="10" + type="default" + /> + + <apn carrier="UTL Internet UG" + apn="utweb" + carrier_id = "1755" + mcc="641" + mnc="11" + proxy="10.76.101.51" + port="8080" + type="default" + /> + + <apn carrier="Orange Internet UG" + carrier_id = "1756" + mcc="641" + mnc="14" + apn="orange.ug" + type="default" + /> + + <apn carrier="Orange MMS" + carrier_id = "1756" + mcc="641" + mnc="14" + apn="orangemms" + mmsc="http://mms/" + type="mms" + /> + + <apn carrier="Warid Telecom Internet UG" + apn="web.waridtel.co.ug" + carrier_id = "1757" + mcc="641" + mnc="22" + proxy="10.5.27.80" + port="8080" + type="default" + /> + + <apn carrier="Spacetel" + carrier_id = "1373" + mcc="642" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Tempo" + carrier_id = "1374" + mcc="642" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Onatel" + carrier_id = "1375" + mcc="642" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Smart Mobile" + carrier_id = "2355" + mcc="642" + mnc="07" + apn="default" + type="default,supl" + /> + + <apn carrier="HiTs Telecom" + carrier_id = "2211" + mcc="642" + mnc="08" + apn="default" + type="default,supl" + /> + + <apn carrier="Leo" + carrier_id = "2212" + mcc="642" + mnc="82" + apn="default" + type="default,supl" + /> + + <apn carrier="mCel" + carrier_id = "1634" + mcc="643" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Movitel" + carrier_id = "2213" + mcc="643" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Vodacom" + carrier_id = "2381" + mcc="643" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1319" + mcc="645" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="MTN" + carrier_id = "1320" + mcc="645" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="ZAMTEL" + carrier_id = "1321" + mcc="645" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Orange MG Internet" + carrier_id = "1606" + mcc="646" + mnc="02" + apn="orangenet" + type="default,supl,agps,fota,dun" + authtype="0" + /> + + <apn carrier="Orange World re" + carrier_id = "1676" + mcc="647" + mnc="00" + apn="orangerun" + user="orange" + password="orange" + type="default,supl" + /> + + <apn carrier="Orange MMS Réunion" + carrier_id = "1676" + mcc="647" + mnc="00" + apn="orangerun.acte" + user="orange" + password="orange" + mmsc="http://mms.orange.re" + mmsproxy="192.168.10.200" + mmsport="8080" + type="mms" + /> + + <apn carrier="OnlyWap" + carrier_id = "1677" + mcc="647" + mnc="02" + apn="onlywap" + user="only" + password="only" + authtype="1" + proxy="10.4.85.50" + port="8080" + type="default,supl" + /> + + <apn carrier="OnlyMMS" + carrier_id = "1677" + mcc="647" + mnc="02" + apn="onlymms" + user="only" + password="only" + authtype="1" + mmsc="http://10.4.85.50:8514" + mmsproxy="10.4.85.50" + mmsport="8080" + type="mms" + /> + + <apn carrier="Free Re" + carrier_id = "2127" + mcc="647" + mnc="03" + apn="free.re" + mmsc="http://mms.free.re" + type="default,supl,mms" + /> + + <apn carrier="Full Internet SRR" + carrier_id = "1008" + mcc="647" + mnc="10" + apn="sl2sfr" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1008" + mcc="647" + mnc="10" + apn="mmssfr" + user="mms" + password="mms" + mmsc="http://mms" + mmsproxy="10.0.224.145" + mmsport="8080" + type="mms" + /> + + <apn carrier="GPRS SRR" + carrier_id = "1008" + mcc="647" + mnc="10" + apn="wapsfr" + user="wap" + password="wap" + proxy="10.0.224.161" + port="8080" + type="default,supl" + /> + + <apn carrier="Coriolis WAP" + carrier_id = "2135" + mcc="647" + mnc="10" + apn="fnetcoriolis" + type="default,supl" + mvno_match_data="12" + mvno_type="gid" + /> + + <apn carrier="Coriolis MMS" + carrier_id = "2135" + mcc="647" + mnc="10" + mmsc="http://mmscoriolis" + mmsproxy="10.143.156.6" + mmsport="8080" + apn="mmscoriolis" + type="mms" + mvno_match_data="12" + mvno_type="gid" + /> + + <apn carrier="Telecel" + carrier_id = "1879" + mcc="648" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="Econet" + carrier_id = "1880" + mcc="648" + mnc="04" + apn="default" + type="default,supl" + /> + + <apn carrier="MTC" + carrier_id = "941" + mcc="649" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="switch" + carrier_id = "2214" + mcc="649" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Leo" + carrier_id = "942" + mcc="649" + mnc="03" + apn="default" + type="default,supl" + /> + + <apn carrier="TNM" + carrier_id = "1625" + mcc="650" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Airtel" + carrier_id = "1626" + mcc="650" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="VCL Internet GPRS" + carrier_id = "2392" + mcc="651" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="VCL MMS GPRS" + carrier_id = "2392" + mcc="651" + mnc="01" + apn="mms" + mmsc="http://mmsc.vodacom4me.co.ls" + mmsproxy="10.113.63.11" + mmsport="8080" + type="mms" + /> + + <apn carrier="Swazi MTN" + carrier_id = "1091" + mcc="653" + mnc="10" + apn="default" + type="default,supl" + /> + + <apn carrier="HURI - SNPT" + carrier_id = "872" + mcc="654" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="LTE.Vodacom" + carrier_id = "24" + mcc="655" + mnc="01" + apn="lte.vodacom.za" + type="default,supl" + /> + + <apn carrier="MMS.Vodacom" + carrier_id = "24" + mcc="655" + mnc="01" + apn="lte.vodacom.za" + mmsc="http://mmsc.vodacom4me.co.za" + mmsproxy="196.6.128.13" + mmsport="8080" + type="mms" + /> + + <apn carrier="Smart.Vodacom" + carrier_id = "24" + mcc="655" + mnc="01" + apn="internet" + type="default,supl" + /> + + <apn carrier="MMS.Vodacom" + carrier_id = "24" + mcc="655" + mnc="01" + apn="mms.vodacom.net" + mmsc="http://mmsc.vodacom4me.co.za" + mmsproxy="196.6.128.13" + mmsport="8080" + type="mms" + /> + + <apn carrier="Telkom Mobile Internet" + carrier_id = "1965" + mcc="655" + mnc="02" + apn="internet" + type="default,supl" + /> + + <apn carrier="Telkom Mobile MMS" + carrier_id = "1965" + mcc="655" + mnc="02" + apn="mms" + mmsc="http://mms.8ta.com:38090/was" + mmsproxy="41.151.254.162" + mmsport="8080" + type="mms" + /> + + <apn carrier="Cell C GPRS" + carrier_id = "1308" + mcc="655" + mnc="07" + apn="internet" + proxy="196.31.116.250" + port="8080" + type="default,supl" + /> + + <apn carrier="Cell C MMS" + carrier_id = "1308" + mcc="655" + mnc="07" + apn="mms" + mmsc="http://mms.cmobile.co.za/" + mmsproxy="196.31.116.250" + mmsport="8080" + type="mms" + /> + + <apn carrier="VIRGIN_INTERNET_1" + carrier_id = "2335" + mcc="655" + mnc="07" + apn="vdata" + proxy="196.31.116.241" + port="8080" + type="default,supl" + mvno_match_data="6550710" + mvno_type="imsi" + /> + + <apn carrier="VIRGIN_INTERNET_2" + carrier_id = "2335" + mcc="655" + mnc="07" + apn="vdata" + proxy="196.31.116.241" + port="9201" + type="default,supl" + mvno_match_data="6550710" + mvno_type="imsi" + /> + + <apn carrier="Virgin_MMS_1" + carrier_id = "2335" + mcc="655" + mnc="07" + apn="vmms" + mmsc="http://mms.virginmobile.co.za" + mmsproxy="196.31.116.242" + mmsport="8080" + type="mms" + mvno_match_data="6550710" + mvno_type="imsi" + /> + + <apn carrier="Virgin_MMS_2" + carrier_id = "2335" + mcc="655" + mnc="07" + apn="vmms" + mmsc="http://mms.virginmobile.co.za" + mmsproxy="196.31.116.242" + mmsport="9201" + type="mms" + mvno_match_data="6550710" + mvno_type="imsi" + /> + + <apn carrier="MTN GPRS" + carrier_id = "1309" + mcc="655" + mnc="10" + apn="myMTN" + user="mtnwap" + password="mtnwap" + authtype="1" + type="default,supl" + /> + + <apn carrier="MTN MMS" + carrier_id = "1309" + mcc="655" + mnc="10" + apn="myMTN" + user="mtnmms" + password="mtnmms" + authtype="1" + mmsc="http://mms.mtn.co.za/mms/wapenc" + mmsproxy="196.11.240.241" + mmsport="8080" + type="mms" + /> + + <apn carrier="Eritel" + carrier_id = "2247" + mcc="657" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="DigiCell" + carrier_id = "570" + mcc="702" + mnc="67" + apn="default" + type="default,supl" + /> + + <apn carrier="Smart" + carrier_id = "2354" + mcc="702" + mnc="99" + apn="default" + type="default,supl" + /> + + <apn carrier="Internet CLARO" + carrier_id = "1520" + mcc="704" + mnc="01" + apn="internet.ideasclaro" + type="default,supl" + /> + + <apn carrier="MMS CLARO" + carrier_id = "1520" + mcc="704" + mnc="01" + apn="mms.ideasclaro" + mmsproxy="216.230.133.66" + mmsport="8080" + mmsc="http://mms.ideasclaro.com:8002" + type="mms" + /> + + <apn carrier="Broadband TIGO" + carrier_id = "1521" + mcc="704" + mnc="02" + apn="broadband.tigo.gt" + type="default,supl" + /> + + <apn carrier="MMS TIGO" + carrier_id = "1521" + mcc="704" + mnc="02" + apn="mms.tigo.gt" + mmsproxy="10.16.17.12" + mmsport="8888" + mmsc="http://mms" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1522" + mcc="704" + mnc="03" + apn="internet.movistar.gt" + user="movistargt" + password="movistargt" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1522" + mcc="704" + mnc="03" + apn="mms.movistar.gt" + user="movistargt" + password="movistargt" + mmsproxy="10.12.22.1" + mmsport="80" + mmsc="http://mms.movistar.gt" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1522" + mcc="704" + mnc="030" + apn="internet.movistar.gt" + user="movistargt" + password="movistargt" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1522" + mcc="704" + mnc="030" + apn="mms.movistar.gt" + user="movistargt" + password="movistargt" + mmsproxy="10.12.22.1" + mmsport="80" + mmsc="http://mms.movistar.gt" + authtype="1" + type="mms" + /> + + <apn carrier="Internet CLARO" + carrier_id = "1954" + mcc="706" + mnc="01" + apn="internet.ideasclaro" + type="default,supl" + /> + + <apn carrier="MMS CLARO" + carrier_id = "1954" + mcc="706" + mnc="01" + apn="mms.ideasclaro" + mmsproxy="216.230.133.66" + mmsport="8080" + mmsc="http://mms.ideasclaro.com:8002" + type="mms" + /> + + <apn carrier="Digicel Internet" + carrier_id = "1087" + mcc="706" + mnc="02" + apn="web.digicelsv.com" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1087" + mcc="706" + mnc="02" + apn="wap.digicelsv.com" + mmsproxy="172.26.5.12" + mmsport="8080" + mmsc="http://mmc.digiceljamaica.com/servlets/mms" + type="mms" + /> + + <apn carrier="Internet Tigo" + carrier_id = "1998" + mcc="706" + mnc="03" + apn="internet.tigo.sv" + type="default,supl" + /> + + <apn carrier="MMS Tigo" + carrier_id = "1998" + mcc="706" + mnc="03" + apn="mms.tigo.sv" + mmsproxy="10.16.17.12" + mmsport="8888" + mmsc="http://mms" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "2009" + mcc="706" + mnc="04" + apn="internet.movistar.sv" + user="movistarsv" + password="movistarsv" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "2009" + mcc="706" + mnc="04" + apn="mms.movistar.sv" + user="movistarsv" + password="movistarsv" + mmsproxy="10.12.20.1" + mmsport="80" + mmsc="http://mms.movistar.sv" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "2009" + mcc="706" + mnc="040" + apn="internet.movistar.sv" + user="movistarsv" + password="movistarsv" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "2009" + mcc="706" + mnc="040" + apn="mms.movistar.sv" + user="movistarsv" + password="movistarsv" + mmsproxy="10.12.20.1" + mmsport="80" + mmsc="http://mms.movistar.sv" + authtype="1" + type="mms" + /> + + <apn carrier="Internet Claro" + carrier_id = "773" + mcc="708" + mnc="001" + apn="internet.ideasclaro" + type="default,supl" + /> + + <apn carrier="MMS Claro" + carrier_id = "773" + mcc="708" + mnc="001" + apn="mms.ideasclaro" + mmsproxy="10.6.32.2" + mmsport="8080" + mmsc="http://10.6.32.27/servlets/mms" + type="mms" + /> + + <apn carrier="INTERNET TIGO" + carrier_id = "1528" + mcc="708" + mnc="02" + apn="internet.tigo.hn" + type="default,supl" + /> + + <apn carrier="MMS TIGO" + carrier_id = "1528" + mcc="708" + mnc="02" + apn="mms.tigo.hn" + mmsproxy="10.16.17.12" + mmsport="8888" + mmsc="http://mms" + type="mms" + /> + + <apn carrier='Honduras:Digicel:Internet' + carrier_id = "2248" + mcc='708' + mnc='04' + apn='web.digicelhn.com' + authtype='1' + type='default' + /> + + <apn carrier='Honduras:Digicel:Mms' + carrier_id = "2248" + mcc='708' + mnc='04' + apn='wap.digicelhn.com' + authtype='1' + mmsc='http://mms.digicelsv.com/servlets/mms' + mmsproxy='172.26.5.12' + mmsport='9201' + type='mms' + /> + + <apn carrier='Honduras:Digicel:Modem' + carrier_id = "2248" + mcc='708' + mnc='04' + apn='wap.digicelhn.com' + port='8080' + authtype='1' + proxy='172.26.5.12' + mmsc='http://www.digicelive.com' + type='dun' + /> + + <apn carrier="INTERNET TIGO" + carrier_id = "1528" + mcc="708" + mnc="020" + apn="internet.tigo.hn" + type="default,supl" + /> + + <apn carrier="MMS TIGO" + carrier_id = "1528" + mcc="708" + mnc="020" + apn="mms.tigo.hn" + mmsproxy="10.16.17.12" + mmsport="8888" + mmsc="http://mms" + type="mms" + /> + + <apn carrier='Honduras:Digicel:Internet:2' + carrier_id = "2248" + mcc='708' + mnc='040' + apn='web.digicelhn.com' + authtype='1' + type='default' + /> + + <apn carrier='Honduras:Digicel:Mms:2' + carrier_id = "2248" + mcc='708' + mnc='040' + apn='wap.digicelhn.com' + authtype='1' + mmsc='http://mms.digicelsv.com/servlets/mms' + mmsproxy='172.26.5.12' + mmsport='9201' + type='mms' + /> + + <apn carrier="Enitel WEB" + carrier_id = "1641" + mcc="710" + mnc="21" + apn="internet.ideasalo.ni" + user="internet" + password="internet" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Enitel MMS" + carrier_id = "1641" + mcc="710" + mnc="21" + apn="mms.indeasalo.ni" + user="mms" + password="mms" + mmsproxy="10.6.32.2" + mmsport="8080" + mmsc="http://10.6.32.27/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "2010" + mcc="710" + mnc="30" + apn="internet.movistar.ni" + user="movistarni" + password="movistarni" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "2010" + mcc="710" + mnc="30" + apn="mms.movistar.ni" + user="movistarni" + password="movistarni" + mmsproxy="10.12.23.1" + mmsport="80" + mmsc="http://mms.movistar.ni" + authtype="1" + type="mms" + /> + + <apn carrier="Yota Nicaragua Internet" + carrier_id = "2458" + mcc="710" + mnc="70" + apn="internet" + type="default,supl" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "2010" + mcc="710" + mnc="300" + apn="internet.movistar.ni" + user="movistarni" + password="movistarni" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "2010" + mcc="710" + mnc="300" + apn="mms.movistar.ni" + user="movistarni" + password="movistarni" + mmsproxy="10.12.23.1" + mmsport="80" + mmsc="http://mms.movistar.ni" + authtype="1" + type="mms" + /> + + <apn carrier="Enitel WEB" + carrier_id = "1642" + mcc="710" + mnc="73" + apn="internet.ideasalo.ni" + user="internet" + password="internet" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Enitel MMS" + carrier_id = "1642" + mcc="710" + mnc="73" + apn="mms.indeasalo.ni" + user="mms" + password="mms" + mmsproxy="10.6.32.2" + mmsport="8080" + mmsc="http://10.6.32.27/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Enitel WEB" + carrier_id = "1642" + mcc="710" + mnc="730" + apn="internet.ideasalo.ni" + user="internet" + password="internet" + authtype="1" + type="default,supl" + /> + + + <apn carrier="Enitel MMS" + carrier_id = "1642" + mcc="710" + mnc="730" + apn="mms.indeasalo.ni" + user="mms" + password="mms" + mmsproxy="10.6.32.2" + mmsport="8080" + mmsc="http://10.6.32.27/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="KOLBI 3G" + carrier_id = "627" + mcc="712" + mnc="01" + apn="kolbi3g" + type="default,supl" + /> + + <apn carrier="Costar Rica:Kolbi:Modem" + carrier_id = "627" + mcc="712" + mnc="01" + apn="kolbi" + type="dun" + authtype="1" + mmsc="http://mimundokolbi.ice.cr" + mmsport="8080" + /> + + <apn carrier="Kolbi_Multimedia" + carrier_id = "627" + mcc="712" + mnc="01" + apn="kolbimundo" + mmsproxy="10.184.202.24" + mmsport="8080" + mmsc="http://mmsice" + type="mms" + /> + + <apn carrier="KOLBI 3G" + carrier_id = "627" + mcc="712" + mnc="02" + apn="kolbi3g" + type="default,supl" + /> + + <apn carrier="Kolbi_Multimedia" + carrier_id = "627" + mcc="712" + mnc="02" + apn="kolbimundo" + mmsproxy="10.184.202.24" + mmsport="8080" + mmsc="http://mmsice" + type="mms" + /> + + <apn carrier="Internet CLARO CR" + carrier_id = "1953" + mcc="712" + mnc="03" + apn="internet.ideasclaro" + user="" + password="" + type="default,supl" + /> + + <apn carrier="MMS CLARO CR" + carrier_id = "1953" + mcc="712" + mnc="03" + apn="mms.ideasclaro" + user="" + password="" + mmsproxy="216.230.133.66" + mmsport="8080" + mmsc="http://mms.ideasclaro.com:8002" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "2003" + mcc="712" + mnc="04" + apn="internet.movistar.cr" + user="movistarcr" + password="movistarcr" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "2003" + mcc="712" + mnc="04" + apn="mms.movistar.cr" + user="movistarcr" + password="movistarcr" + mmsproxy="10.221.79.83" + mmsport="80" + mmsc="http://mms.movistar.cr" + authtype="1" + type="mms" + /> + + <apn carrier="Internet Tuyo" + carrier_id = "2267" + mcc="712" + mnc="019" + apn="tm7datos" + type="default,supl" + /> + + <apn carrier="MMS Tuyo" + carrier_id = "2267" + mcc="712" + mnc="019" + apn="tm7mms" + mmsproxy="10.186.181.5" + mmsport="3128" + mmsc="http://mmsc.tuyomovil.com:1981" + type="mms" + /> + + <apn carrier="Internet Tuyo" + carrier_id = "2267" + mcc="712" + mnc="190" + apn="tm7datos" + type="default,supl" + /> + + <apn carrier="MMS Tuyo" + carrier_id = "2267" + mcc="712" + mnc="190" + apn="tm7mms" + mmsproxy="10.186.181.5" + mmsport="3128" + mmsc="http://mmsc.tuyomovil.com:1981" + type="mms" + /> + + <apn carrier="Internet Fullmovil" + mcc="712" + mnc="20" + apn="datos.fullmovil.cr" + type="default,supl" + /> + + <apn carrier="Internet" + carrier_id = "973" + mcc="714" + mnc="01" + apn="apn01.cwpanama.com.pa" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "973" + mcc="714" + mnc="01" + apn="apn02.cwpanama.com.pa" + mmsproxy="172.25.3.5" + mmsport="8080" + mmsc="http://mms.zonamovil.com.pa" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "974" + mcc="714" + mnc="02" + apn="internet.movistar.pa" + user="movistarpa" + password="movistarpa" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "974" + mcc="714" + mnc="02" + apn="mms.movistar.pa" + user="movistarpamms" + password="movistarpa" + mmsproxy="10.12.21.1" + mmsport="80" + mmsc="http://mms.movistar.pa" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "974" + mcc="714" + mnc="020" + apn="internet.movistar.pa" + user="movistarpa" + password="movistarpa" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "974" + mcc="714" + mnc="020" + apn="mms.movistar.pa" + user="movistarpamms" + password="movistarpa" + mmsproxy="10.12.21.1" + mmsport="80" + mmsc="http://mms.movistar.pa" + authtype="1" + type="mms" + /> + + <apn carrier="WEB Claro" + carrier_id = "1925" + mcc="714" + mnc="03" + apn="web.claro.com.pa" + user="CLAROWEB" + password="CLAROWEB" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Claro" + carrier_id = "1925" + mcc="714" + mnc="03" + apn="mms.claro.com.pa" + user="CLAROMMS" + password="CLAROMMS" + mmsproxy="10.240.3.129" + mmsport="8799" + mmsc="http://www.claro.com.pa/mms/" + authtype="1" + type="mms" + /> + + <apn carrier="Digicel Internet" + carrier_id = "1926" + mcc="714" + mnc="04" + apn="web.digicelpanama.com" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1926" + mcc="714" + mnc="04" + apn="wap.digicelpanama.com" + mmsproxy="172.27.99.99" + mmsport="8080" + mmsc="http://mmc.digicelpanama.com/servlets/mms" + type="mms" + /> + + <apn carrier='Panama:Digicel:Internet:2' + carrier_id = "1926" + mcc='714' + mnc='040' + apn='web.digicelpanama.com' + authtype='1' + type='default' + /> + + <apn carrier='Panama:Digicel:Mms:2' + carrier_id = "1926" + mcc='714' + mnc='040' + apn='wap.digicelpanama.com' + authtype='1' + mmsc='http://mmc.digicelpanama.com/servlets/mms' + mmsproxy='172.27.99.99' + mmsport='9201' + type='mms' + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1929" + mcc="716" + mnc="06" + apn="movistar.pe" + user="movistar@datos" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1929" + mcc="716" + mnc="06" + apn="mms.movistar.pe" + user="movistar@mms" + password="movistar" + mmsproxy="200.4.196.118" + mmsport="8080" + mmsc="http://mmsc.telefonicamovistar.com.pe:8088/mms/" + authtype="1" + type="mms" + /> + + <apn carrier="CLARO DATOS" + carrier_id = "1647" + mcc="716" + mnc="10" + apn="claro.pe" + user="claro" + password="claro" + authtype="1" + type="default,supl" + /> + + <apn carrier="CLARO MMS" + carrier_id = "1647" + mcc="716" + mnc="10" + apn="mms.claro.pe" + user="claro" + password="claro" + mmsproxy="192.168.231.30" + mmsport="80" + mmsc="http://claro/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="Bitel - Internet" + carrier_id = "2359" + mcc="716" + mnc="15" + apn="bitel" + authtype="1" + type="default,supl" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Bitel - MMS" + carrier_id = "2359" + mcc="716" + mnc="15" + apn="bitel-mms" + mmsc="http://181.176.241.99:8080" + mmsproxy="10.121.144.3" + mmsport="8000" + authtype="1" + type="mms" + protocol="IP" + roaming_protocol="IP" + /> + + <apn carrier="Entel PE" + carrier_id = "1930" + mcc="716" + mnc="17" + apn="entel.pe" + authtype="0" + type="default,dun" + protocol="IP" + /> + + <apn carrier="Entel MMS" + carrier_id = "1930" + mcc="716" + mnc="17" + apn="mms.entel.pe" + mmsc="http://mms.entel.pe" + mmsproxy="10.0.215.74" + mmsport="8080" + authtype="0" + type="mms" + protocol="IP" + /> + + <apn carrier="Entel Location" + carrier_id = "1930" + mcc="716" + mnc="17" + apn="location.entel.pe" + port="7275" + server="http://location.entel.pe" + authtype="0" + type="supl" + protocol="IP" + /> + + <apn carrier="Servicio_WEB" + carrier_id="2249" + mcc="722" + mnc="01" + apn="internet.movil" + user="internet" + password="internet" + authtype="1" + type="default" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + mvno_type="spn" + mvno_match_data="Tuenti" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1337" + mcc="722" + mnc="07" + apn="wap.gprs.unifon.com.ar" + user="wap" + password="wap" + authtype="1" + type="default,supl" + protocol="IPV4V6" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1337" + mcc="722" + mnc="07" + apn="mms.gprs.unifon.com.ar" + user="mms" + password="mms" + mmsproxy="200.68.32.239" + mmsport="8080" + mmsc="http://mms.movistar.com.ar" + authtype="1" + type="mms" + /> + + <apn carrier="Claro AR" + carrier_id = "1338" + mcc="722" + mnc="31" + apn="igprs.claro.com.ar" + mmsc="http://mms.claro.com.ar" + type="default,supl,mms" + /> + + <apn carrier="Claro AR" + carrier_id = "1338" + mcc="722" + mnc="310" + apn="igprs.claro.com.ar" + mmsc="http://mms.claro.com.ar" + type="default,supl,mms" + /> + + <apn carrier="Personal Datos" + carrier_id = "1341" + mcc="722" + mnc="34" + apn="datos.personal.com" + user="datos" + password="datos" + authtype="1" + type="default,supl" + /> + + <apn carrier="Argentina:Personal:DUN" + carrier_id = "1341" + mcc="722" + mnc="34" + apn="internet.personal.com" + type="dun" + user="internet" + password="internet" + authtype="0" + /> + + <apn carrier="Personal MMS" + carrier_id = "1341" + mcc="722" + mnc="34" + apn="mms" + user="mms" + password="mms" + mmsproxy="172.25.7.31" + mmsport="8080" + mmsc="http://mms.personal.com" + authtype="1" + type="mms" + /> + + <apn carrier='Argentina:Nuestro:MMS' + carrier_id = "2250" + mcc='722' + mnc='36' + apn='mms.nuestro.com.ar' + authtype='0' + mmsc='http://mms.nuestro.com.ar' + mmsproxy='172.16.0.20' + mmsport='8080' + type='mms' + user='mms' + /> + + <apn carrier='Argentina:Nuestro:Internet' + carrier_id = "2250" + mcc='722' + mnc='36' + apn='gprs.nuestro.com.ar' + authtype='0' + type='default' + user='gprs' + /> + + <apn carrier='Argentina:Personal :Datos' + carrier_id = "1341" + mcc='722' + mnc='340' + apn='datos.personal.com' + authtype='0' + type='default' + user='gprs' + password='adgj' + /> + + <apn carrier='Argentina:Personal :DUN' + carrier_id = "1341" + mcc='722' + mnc='340' + apn='internet.personal.com' + authtype='0' + type='dun' + user='internet' + password='internet' + /> + + <apn carrier='Argentina:Personal :MMS' + carrier_id = "1341" + mcc='722' + mnc='340' + apn='mms' + authtype='0' + mmsc='http://mms.personal.com' + mmsproxy='172.25.7.31' + mmsport='8080' + type='mms' + user='mms' + password='mms' + /> + + <apn carrier="Personal Datos" + carrier_id = "1341" + mcc="722" + mnc="341" + apn="datos.personal.com" + user="datos" + password="datos" + authtype="1" + type="default,supl" + /> + + <apn carrier="Argentina:Personal: DUN" + carrier_id = "1341" + mcc="722" + mnc="341" + apn="internet.personal.com" + type="dun" + user="internet" + password="internet" + authtype="0" + /> + + <apn carrier="Personal MMS" + carrier_id = "1341" + mcc="722" + mnc="341" + apn="mms" + user="mms" + password="mms" + mmsproxy="172.25.7.31" + mmsport="8080" + mmsc="http://mms.personal.com" + authtype="1" + type="mms" + /> + + <apn carrier="TIM Connect" + carrier_id = "1385" + mcc="724" + mnc="02" + apn="timbrasil.br" + user="tim" + password="tim" + mmsc="http://mms.tim.br" + mmsproxy="189.40.191.96" + mmsport="8080" + authtype="1" + protocol="IPV4V6" + type="default,supl,mms" + /> + + <apn carrier="TIM Connect" + carrier_id = "1385" + mcc="724" + mnc="03" + apn="timbrasil.br" + user="tim" + password="tim" + mmsc="http://mms.tim.br" + mmsproxy="189.40.191.96" + mmsport="8080" + authtype="1" + protocol="IPV4V6" + type="default,supl,mms" + /> + + <apn carrier="TIM Connect" + carrier_id = "1385" + mcc="724" + mnc="04" + apn="timbrasil.br" + user="tim" + password="tim" + mmsc="http://mms.tim.br" + mmsproxy="189.40.191.96" + mmsport="8080" + authtype="1" + protocol="IPV4V6" + type="default,supl,mms" + /> + + <apn carrier="Java Session" + carrier_id = "529" + mcc="724" + mnc="05" + apn="java.claro.com.br" + user="claro" + password="claro" + type="default,supl" + /> + + <apn carrier="Claro Foto" + carrier_id = "529" + mcc="724" + mnc="05" + apn="mms.claro.com.br" + user="claro" + password="claro" + mmsc="http://mms.claro.com.br" + mmsproxy="200.169.126.10" + mmsport="8799" + authtype="1" + type="mms" + /> + + <apn carrier="Vivo MMS" + carrier_id = "530" + mcc="724" + mnc="06" + apn="mms.vivo.com.br" + user="vivo" + password="vivo" + mmsc="http://termnat.vivomms.com.br:8088/mms" + mmsproxy="200.142.130.104" + mmsport="80" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier="Vivo Internet" + carrier_id = "530" + mcc="724" + mnc="06" + apn="zap.vivo.com.br" + user="vivo" + password="vivo" + authtype="1" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="SCTL MMS" + carrier_id = "1388" + mcc="724" + mnc="07" + apn="mms.sercomtel.com.br" + user="sercomtel" + password="sercomtel" + mmsc="http://mms.claro.com.br" + mmsproxy="200.169.126.10" + mmsport="8799" + type="mms" + /> + + <apn carrier="SCTL GPRS" + carrier_id = "1388" + mcc="724" + mnc="07" + apn="sercomtel.com.br" + user="sercomtel" + password="sercomtel" + type="default,supl" + /> + + <apn carrier="Vivo Internet" + carrier_id = "530" + mcc="724" + mnc="10" + apn="zap.vivo.com.br" + user="vivo" + password="vivo" + authtype="1" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="Vivo MMS" + carrier_id = "530" + mcc="724" + mnc="10" + apn="mms.vivo.com.br" + user="vivo" + password="vivo" + mmsc="http://termnat.vivomms.com.br:8088/mms" + mmsproxy="200.142.130.104" + mmsport="80" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier="Vivo MMS" + carrier_id = "530" + mcc="724" + mnc="11" + apn="mms.vivo.com.br" + user="vivo" + password="vivo" + mmsc="http://termnat.vivomms.com.br:8088/mms" + mmsproxy="200.142.130.104" + mmsport="80" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier="Vivo Internet" + carrier_id = "530" + mcc="724" + mnc="11" + apn="zap.vivo.com.br" + user="vivo" + password="vivo" + authtype="1" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier='Sercomtel:Dados' + carrier_id = "539" + mcc='724' + mnc='15' + apn='sercomtel.com.br' + authtype='1' + type='default' + user='sercomtel' + password='sercomtel' + /> + + <apn carrier='Sercomtel:MMS' + carrier_id = "539" + mcc='724' + mnc='15' + apn='mms.sercomtel.com.br' + authtype='1' + mmsc='http://mms.claro.com.br' + mmsproxy='200.169.126.10' + mmsport='8799' + type='mms' + user='sercomtel' + password='sercomtel' + /> + + <apn carrier='Sercomtel:Modem' + carrier_id = "539" + mcc='724' + mnc='15' + apn='sercomtel.com.br' + authtype='1' + type='dun' + user='sercomtel' + password='sercomtel' + /> + + <apn carrier="Oi GPRS Internet" + carrier_id = "540" + mcc="724" + mnc="16" + apn="gprs.oi.com.br" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="MMS GPRS" + carrier_id = "540" + mcc="724" + mnc="16" + apn="mmsgprs.oi.com.br" + user="oimms" + password="oioioi" + mmsc="http://200.222.42.204:8002" + mmsproxy="192.168.10.50" + mmsport="3128" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier="Surf" + mcc="724" + mnc="17" + apn="internet.br" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Surf" + /> + + <apn carrier="LIGUE 4G Internet" + mcc="724" + mnc="18" + apn="iot4u.br" + authtype="1" + user="arqia" + password="arqia" + type="default" + protocol="IPV4V6" + roaming_protocol="IPV4" + mvno_type="spn" + mvno_match_data="LIGUE" + /> + + <apn carrier="LIGUE 4G IMS" + mcc="724" + mnc="18" + apn="ims" + type="ims" + protocol="IPV4V6" + roaming_protocol="IPV4" + mvno_type="spn" + mvno_match_data="LIGUE" + /> + + <apn carrier="TelemigC GPRS" + carrier_id = "543" + mcc="724" + mnc="19" + apn="gprs.telemigcelular.com.br" + user="celular" + password="celular" + type="default,supl" + /> + + <apn carrier="MMS Telemig" + carrier_id = "543" + mcc="724" + mnc="19" + apn="mmsgprs.telemigcelular.com.br" + user="celular" + password="celular" + mmsc="http://mms.telemigcelular.com.br" + mmsproxy="200.192.230.142" + mmsport="8080" + type="mms" + /> + + <apn carrier="LIGUE Internet" + mcc="724" + mnc="21" + apn="internet.ligue.vc" + type="default" + protocol="IPV4V6" + /> + + <apn carrier="LIGUE IMS" + mcc="724" + mnc="21" + apn="ims" + type="ims" + protocol="IPV4V6" + /> + + <apn carrier="Vivo Internet" + carrier_id = "530" + mcc="724" + mnc="23" + apn="zap.vivo.com.br" + user="vivo" + password="vivo" + authtype="1" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="Vivo MMS" + carrier_id = "530" + mcc="724" + mnc="23" + apn="mms.vivo.com.br" + user="vivo" + password="vivo" + mmsc="http://termnat.vivomms.com.br:8088/mms" + mmsproxy="200.142.130.104" + mmsport="80" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier="OI:INTERNET:2" + carrier_id = "1389" + mcc="724" + mnc="24" + apn="gprs.oi.com.br" + authtype="1" + type="default,dun" + user="oi" + password="oi" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Oi:MMS:2" + carrier_id = "1389" + mcc="724" + mnc="24" + apn="mmsgprs.oi.com.br" + authtype="1" + mmsc="http://200.222.42.204:8002" + mmsproxy="192.168.10.50" + mmsport="3128" + type="mms" + user="oimms" + password="oioioi" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + /> + + <apn carrier="Oi GPRS Internet" + carrier_id = "1389" + mcc="724" + mnc="31" + apn="gprs.oi.com.br" + protocol="IPV4V6" + type="default,supl" + /> + + <apn carrier="MMS GPRS" + carrier_id = "1389" + mcc="724" + mnc="31" + apn="mmsgprs.oi.com.br" + user="oimms" + password="oioioi" + mmsc="http://200.222.42.204:8002" + mmsproxy="192.168.10.50" + mmsport="3128" + authtype="1" + protocol="IPV4V6" + type="mms" + /> + + <apn carrier='CTBC:Dados:1' + carrier_id = "1390" + mcc='724' + mnc='32' + apn='ctbc.br' + authtype='1' + type='default' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:Modem:1' + carrier_id = "1390" + mcc='724' + mnc='32' + apn='ctbc.br' + authtype='1' + type='dun' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:MMS:1' + carrier_id = "1390" + mcc='724' + mnc='32' + apn='mms.ctbc.br' + authtype='1' + mmsc='http://mms.ctbccelular.com.br/was' + mmsproxy='172.29.7.70' + mmsport='8080' + type='mms' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:Dados:2' + carrier_id = "1390" + mcc='724' + mnc='33' + apn='ctbc.br' + authtype='1' + type='default' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:Modem:2' + carrier_id = "1390" + mcc='724' + mnc='33' + apn='ctbc.br' + authtype='1' + type='dun' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:MMS:2' + carrier_id = "1390" + mcc='724' + mnc='33' + apn='mms.ctbc.br' + authtype='1' + mmsc='http://mms.ctbccelular.com.br/was' + mmsproxy='172.29.7.70' + mmsport='8080' + type='mms' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:Dados:3' + carrier_id = "1390" + mcc='724' + mnc='34' + apn='ctbc.br' + authtype='1' + type='default' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:Modem:3' + carrier_id = "1390" + mcc='724' + mnc='34' + apn='ctbc.br' + authtype='1' + type='dun' + user='CTBC' + password='1212' + /> + + <apn carrier='CTBC:MMS:3' + carrier_id = "1390" + mcc='724' + mnc='34' + apn='mms.ctbc.br' + authtype='1' + mmsc='http://mms.ctbccelular.com.br/was' + mmsproxy='172.29.7.70' + mmsport='8080' + type='mms' + user='CTBC' + password='1212' + /> + + <apn carrier='Nextel MMS' + carrier_id = "1383" + mcc='724' + mnc='39' + apn='mms.nextel3g.net.br' + authtype='0' + mmsc='http://3gmms.nextel3g.net.br' + mmsproxy='129.192.129.104' + mmsport='8080' + type='mms' + protocol='IPV4V6' + roaming_protocol='IPV4V6' + /> + + <apn carrier='Nextel WAP' + carrier_id = "1383" + mcc='724' + mnc='39' + apn='wap.nextel3g.net.br' + authtype='0' + type='default,dun' + protocol='IPV4V6' + roaming_protocol='IPV4V6' + /> + + <apn carrier='Porto Seguro Conecta' + carrier_id = "2215" + mcc='724' + mnc='54' + authtype='0' + type='default,dun' + apn='portoconecta.br' + /> + + <apn carrier="Internet Movil" + carrier_id = "1427" + mcc="730" + mnc="01" + apn="bam.entelpcs.cl" + user="entelpcs" + password="entelpcs" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Entel" + carrier_id = "1427" + mcc="730" + mnc="01" + apn="mms.entelpcs.cl" + user="entelpcs" + password="entelpcs" + mmsproxy="10.99.0.10" + mmsport="8080" + mmsc="http://mmsc.entelpcs.cl" + authtype="1" + type="mms" + /> + + <apn carrier='Internet Nextel' + carrier_id = "1430" + mcc='730' + mnc='09' + apn='wap.nextelmovil.cl' + authtype='0' + type='default' + /> + + <apn carrier='MMS Nextel' + carrier_id = "1430" + mcc='730' + mnc='09' + apn='mms.nextelmovil.cl' + authtype='0' + mmsc='http://3gmms.nextelmovil.cl' + mmsproxy='129.192.129.104' + mmsport='8080' + type='mms' + /> + + <apn carrier="Internet Movil" + carrier_id = "1427" + mcc="730" + mnc="10" + apn="bam.entelpcs.cl" + user="entelpcs" + password="entelpcs" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Entel" + carrier_id = "1427" + mcc="730" + mnc="10" + apn="mms.entelpcs.cl" + user="entelpcs" + password="entelpcs" + mmsproxy="10.99.0.10" + mmsport="8080" + mmsc="http://mmsc.entelpcs.cl" + authtype="1" + type="mms" + /> + + <apn carrier="Movistar APLICACIONES" + carrier_id = "1428" + mcc="730" + mnc="02" + apn="wap.tmovil.cl" + user="wap" + password="wap" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1428" + mcc="730" + mnc="02" + apn="mms.tmovil.cl" + user="mms" + password="mms" + mmsproxy="172.17.8.10" + mmsport="8080" + mmsc="http://mms.movistar.cl" + authtype="1" + type="mms" + /> + + <apn carrier="Banda Ancha Movil" + carrier_id = "1429" + mcc="730" + mnc="03" + apn="bam.clarochile.cl" + user="clarochile" + password="clarochile" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Claro" + carrier_id = "1429" + mcc="730" + mnc="03" + apn="mms.clarochile.cl" + user="clarochile" + password="clarochile" + mmsproxy="172.23.200.200" + mmsport="8080" + mmsc="http://mms.clarochile.cl" + authtype="1" + type="mms" + /> + + <apn carrier="web" + carrier_id = "1428" + mcc="730" + mnc="07" + apn="web.gtdmovil.cl" + user="webgtd" + password="webgtd" + authtype="1" + type="default,supl" + /> + + <apn carrier="Internet" + carrier_id = "2216" + mcc="730" + mnc="08" + apn="movil.vtr.com" + user="vtrmovil" + password="vtrmovil" + authtype="2" + type="default,supl" + /> + + <apn carrier="Wap" + carrier_id = "2216" + mcc="730" + mnc="08" + apn="wap.vtr.com" + proxy="192.168.94.210" + port="9028" + user="" + password="" + authtype="0" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "2216" + mcc="730" + mnc="08" + apn="mms.vtr.com" + user="mms" + password="" + mmsc="http://192.168.94.162:19090/was" + mmsproxy="192.168.94.210" + mmsport="9028" + authtype="0" + type="mms" + /> + + <apn carrier="Internet Movil" + carrier_id = "1427" + mcc="730" + mnc="10" + apn="bam.entelpcs.cl" + user="entelpcs" + password="entelpcs" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Entel PCS" + carrier_id = "1427" + mcc="730" + mnc="10" + apn="mms.entelpcs.cl" + user="entelpcs" + password="entelpcs" + mmsc="http://mmsc.entelpcs.cl" + mmsproxy="10.99.0.10" + mmsport="8080" + authtype="1" + type="mms" + /> + + <apn carrier='Movistar INTERNET' + mcc='732' + mnc='12' + apn='internet.movistar.com.co' + authtype='1' + type='default, dun' + user='movistar' + password='movistar' + /> + + <apn carrier='Movistar MMS' + mcc='732' + mnc='12' + apn='mms.movistar.com.co' + authtype='1' + mmsc='http://mms.movistar.com.co' + mmsproxy='192.168.222.7' + mmsport='9001' + type='mms' + user='movistar' + password='movistar' + /> + + <apn carrier="COMCEL" + carrier_id = "1442" + mcc="732" + mnc="101" + apn="internet.comcel.com.co" + user="COMCELWEB" + password="COMCELWEB" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Comcel 3GSM" + carrier_id = "1442" + mcc="732" + mnc="101" + apn="mms.comcel.com.co" + user="COMCELMMS" + password="COMCELMMS" + mmsproxy="198.228.90.225" + mmsport="8799" + mmsc="http://www.comcel.com.co/mms/" + authtype="1" + type="mms" + /> + + <apn carrier="TIGO WEB" + carrier_id = "624" + mcc="732" + mnc="103" + apn="web.colombiamovil.com.co" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="TIGO Multimedia" + carrier_id = "624" + mcc="732" + mnc="103" + apn="mms.colombiamovil.com.co" + user="mms-cm1900" + password="mms-cm1900" + mmsproxy="190.102.206.48" + mmsport="8080" + mmsc="http://mms.ola.com.co" + authtype="1" + type="mms" + /> + + <apn carrier="Internet ETB" + carrier_id = "2218" + mcc="732" + mnc="103" + apn="moviletb.net.co" + type="default,dun" + user="etb" + password="etb" + authtype="0" + mvno_match_data="ETB MOVI" + mvno_type="spn" + /> + + <apn carrier="Internet ETB" + carrier_id = "2218" + mcc="732" + mnc="103" + apn="moviletb.net.co" + type="default,dun" + user="etb" + password="etb" + authtype="0" + mvno_match_data="ETB MOVI" + mvno_type="spn" + /> + + <apn carrier="Internet Éxito" + carrier_id = "2337" + mcc="732" + mnc="103" + apn="movilexito.net.co" + type="default,dun" + authtype="1" + mvno_match_data="movil exito" + mvno_type="spn" + /> + + <apn carrier="UNE" + carrier_id = "2338" + mcc="732" + mnc="103" + apn="www.une.net.co" + type="default,dun" + user="une" + password="une" + authtype="0" + mvno_match_data="UNE" + mvno_type="spn" + /> + + <apn carrier="TIGO WEB" + carrier_id = "624" + mcc="732" + mnc="111" + apn="web.colombiamovil.com.co" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="TIGO Multimedia" + carrier_id = "624" + mcc="732" + mnc="111" + apn="mms.colombiamovil.com.co" + user="mms-cm1900" + password="mms-cm1900" + mmsproxy="190.102.206.48" + mmsport="8080" + mmsc="http://mms.ola.com.co" + authtype="1" + type="mms" + /> + + <apn carrier="Internet ETB" + carrier_id = "2218" + mcc="732" + mnc="111" + apn="moviletb.net.co" + type="default,dun" + user="etb" + password="etb" + authtype="0" + mvno_match_data="ETB MOVIL" + mvno_type="spn" + /> + + <apn carrier="Internet Éxito" + carrier_id = "2337" + mcc="732" + mnc="111" + apn="movilexito.net.co" + type="default,dun" + authtype="1" + mvno_match_data="movil exito" + mvno_type="spn" + /> + + <apn carrier="UNE" + carrier_id = "2338" + mcc="732" + mnc="111" + apn="www.une.net.co" + type="default,dun" + user="une" + password="une" + authtype="0" + mvno_match_data="UNE" + mvno_type="spn" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "625" + mcc="732" + mnc="123" + apn="internet.movistar.com.co" + user="movistar" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "625" + mcc="732" + mnc="123" + apn="mms.movistar.com.co" + user="movistar" + password="movistar" + mmsproxy="192.168.222.7" + mmsport="9001" + mmsc="http://mms.movistar.com.co" + authtype="1" + type="mms" + /> + + <apn carrier="Virgin Mobile" + carrier_id = "2339" + mcc="732" + mnc="123" + apn="web.vmc.net.co" + type="default,supl,internet" + authtype="1" + mvno_match_data="Virgin Mobile" + mvno_type="spn" + /> + + <apn carrier="Avantel" + carrier_id = "626" + mcc="732" + mnc="130" + apn="lte.avantel.com.co" + authtype="0" + type="default" + /> + + <apn carrier="ETB 4G" + carrier_id = "2218" + mcc="732" + mnc="187" + apn="internetmovil.etb.net.co" + authtype="0" + type="default" + /> + + <apn carrier="Digitel 412" + carrier_id = "1870" + mcc="734" + mnc="01" + apn="internet.digitel.ve" + type="default,supl" + /> + + <apn carrier="Venezuela:Digitel:MODEM:1" + carrier_id = "1870" + mcc="734" + mnc="01" + apn="gprsweb.digitel.ve" + type="dun" + authtype="1" + /> + + <apn carrier="MMS" + carrier_id = "1870" + mcc="734" + mnc="01" + apn="expresate.digitel.ve" + mmsproxy="10.99.0.10" + mmsport="8080" + mmsc="http://mms.412.com.ve/servlets/mms" + type="mms" + /> + + <apn carrier="Digitel 412" + carrier_id = "1871" + mcc="734" + mnc="02" + apn="internet.digitel.ve" + type="default,supl" + /> + + <apn carrier="Venezuela:Digitel:MODEM:2" + carrier_id = "1871" + mcc="734" + mnc="02" + apn="gprsweb.digitel.ve" + type="dun" + authtype="1" + /> + + <apn carrier="MMS" + carrier_id = "1871" + mcc="734" + mnc="02" + apn="expresate.digitel.ve" + mmsproxy="10.99.0.10" + mmsport="8080" + mmsc="http://mms.412.com.ve/servlets/mms" + type="mms" + /> + + <apn carrier="Digitel 412" + carrier_id = "1872" + mcc="734" + mnc="03" + apn="internet.digitel.ve" + type="default,supl" + /> + + <apn carrier="Venezuela:Digitel:MODEM:3" + carrier_id = "1872" + mcc="734" + mnc="03" + apn="gprsweb.digitel.ve" + type="dun" + authtype="1" + /> + + <apn carrier="MMS" + carrier_id = "1872" + mcc="734" + mnc="03" + apn="expresate.digitel.ve" + mmsproxy="10.99.0.10" + mmsport="8080" + mmsc="http://mms.412.com.ve/servlets/mms" + type="mms" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1873" + mcc="734" + mnc="04" + apn="internet.movistar.ve" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1873" + mcc="734" + mnc="04" + apn="mms.movistar.ve" + mmsproxy="200.35.64.73" + mmsport="9001" + mmsc="http://mms.movistar.com.ve:8088/mms" + type="mms" + /> + + <apn carrier="Movistar WAP" + carrier_id = "1873" + mcc="734" + mnc="04" + apn="wap.movistar.ve" + mmsproxy="200.35.64.73" + mmsport="9001" + type="default,supl" + /> + + <apn carrier="MODEM" + carrier_id = "1874" + mcc="734" + mnc="06" + apn="int.movilnet.com.ve" + type="default,supl" + /> + + <apn carrier="MMS" + carrier_id = "1874" + mcc="734" + mnc="06" + apn="mm.movilnet.com.ve" + mmsproxy="192.168.16.12" + mmsport="8080" + mmsc="http://mms2.movilnet.com.ve/servlets/mms" + type="mms" + /> + + <apn carrier="VIVA3G" + carrier_id = "1380" + mcc="736" + mnc="01" + apn="internet.nuevatel.com" + user="" + password="" + proxy="192.168.101.4" + port="3128" + authtype="1" + type="default,supl" + /> + + <apn carrier="VIVAMMS" + carrier_id = "1380" + mcc="736" + mnc="01" + apn="mms.nuevatel.com" + user="" + password="" + mmsproxy="192.168.101.4" + mmsport="3128" + mmsc="http://mmsgw.nuevatel.com:1981" + authtype="1" + type="mms" + /> + + <apn carrier="ENTEL WAP GPRS" + carrier_id = "1381" + mcc="736" + mnc="02" + apn="wap.movil.com.bo" + user="" + password="" + proxy="172.27.7.10" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="ENTEL MMS GPRS" + carrier_id = "1381" + mcc="736" + mnc="02" + apn="mms.movil.com.bo" + user="" + password="" + mmsproxy="172.27.7.10" + mmsport="8080" + mmsc="http://mms.movil.com.bo/servlets/mms" + authtype="1" + type="mms" + /> + + <apn carrier="WAPTIGO" + carrier_id = "1382" + mcc="736" + mnc="03" + apn="wap.tigo.bo" + user="" + password="" + proxy="172.25.100.8" + port="8080" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMSTIGO" + carrier_id = "1382" + mcc="736" + mnc="03" + apn="mms.tigo.bo" + user="" + password="" + mmsproxy="172.25.100.8" + mmsport="8080" + mmsc="http://mms" + authtype="1" + type="mms" + /> + + <apn carrier="Digicel" + carrier_id = "1525" + mcc="738" + mnc="01" + apn="default" + type="default,supl" + /> + + <apn carrier="Guyana:Digicel:Modem" + carrier_id = "1525" + mcc="738" + mnc="01" + apn="wap.digicelgy.com" + type="dun" + user="wap" + password="wap" + authtype="1" + mmsc="http://www.digicelive.com" + proxy="172.20.6.12" + port="8080" + /> + + <apn carrier="Guyana:Digicel:Mms" + carrier_id = "1525" + mcc="738" + mnc="01" + apn="wap.digicelgy.com" + type="mms" + user="wap" + password="wap" + authtype="1" + mmsproxy="172.20.6.12" + mmsc="http://mmc.digicelgy.com/servlets/mms" + mmsport="9201" + /> + + <apn carrier="GT&T Cellink Plus" + carrier_id = "2217" + mcc="738" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1472" + mcc="740" + mnc="00" + apn="internet.movistar.com.ec" + user="movistar" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1472" + mcc="740" + mnc="00" + apn="mms.movistar.com.ec" + user="movistar" + password="movistar" + mmsproxy="10.3.5.50" + mmsport="9001" + mmsc="http://mms.movistar.com.ec:8088/mms/" + authtype="1" + type="mms" + /> + + <apn carrier="Internet Claro" + carrier_id = "1473" + mcc="740" + mnc="01" + apn="internet.claro.com.ec" + type="default,supl" + /> + + <apn carrier="MMS Claro" + carrier_id = "1473" + mcc="740" + mnc="01" + apn="mms.claro.com.ec" + user="portamms" + password="portamms2003" + mmsproxy="216.250.208.94" + mmsport="8799" + mmsc="http://iesmms.porta.com.ec/" + authtype="1" + type="mms" + /> + + <apn carrier="Internet Claro" + carrier_id = "1473" + mcc="740" + mnc="010" + apn="internet.claro.com.ec" + type="default,supl" + /> + + <apn carrier="MMS Claro" + carrier_id = "1473" + mcc="740" + mnc="010" + apn="mms.claro.com.ec" + user="portamms" + password="portamms2003" + mmsproxy="216.250.208.94" + mmsport="8799" + mmsc="http://iesmms.porta.com.ec/" + authtype="1" + type="mms" + /> + + <apn carrier="CNT 3G" + carrier_id = "1474" + mcc="740" + mnc="02" + apn="internet3gsp.alegro.net.ec" + type="default,supl" + /> + + <apn carrier="CNT MMS" + carrier_id = "1474" + mcc="740" + mnc="02" + apn="mms.alegro.net.ec" + mmsproxy="10.4.85.3" + mmsport="8080" + mmsc="http://mms.alegro.net.ec/mms/" + type="mms" + /> + + <apn carrier="VOX INTERNET" + carrier_id = "1672" + mcc="744" + mnc="01" + apn="vox.internet" + authtype="1" + type="default,supl" + /> + + <apn carrier="Paraguay:Voxx:Modem" + carrier_id = "1672" + mcc="744" + mnc="01" + apn="vox.wap" + type="dun" + authtype="1" + mmsproxy="172.24.97.29" + mmsc="http://www.vox.com.py/" + port="8080" + /> + + <apn carrier="VOX MMS" + carrier_id = "1672" + mcc="744" + mnc="01" + apn="vox.mms" + user="vox" + password="vox" + mmsproxy="172.24.97.29" + mmsport="8080" + mmsc="http://mms.vox.com.py/mmsc" + authtype="1" + type="mms" + /> + + <apn carrier="Claro PY" + carrier_id = "1673" + mcc="744" + mnc="02" + apn="igprs.claro.com.py" + user="ctigprs" + password="ctigprs999" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS GPRS PY" + carrier_id = "1673" + mcc="744" + mnc="02" + apn="mms.ctimovil.com.py" + user="ctimms" + password="ctimms999" + mmsproxy="170.51.255.240" + mmsport="8080" + mmsc="http://mms.ctimovil.com.py" + authtype="1" + type="mms" + /> + + <apn carrier="TIGO PY" + carrier_id = "1927" + mcc="744" + mnc="04" + apn="internet.tigo.py" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS Tigo" + carrier_id = "1927" + mcc="744" + mnc="04" + apn="mms.tigo.py" + user="tigo" + password="tigo" + mmsproxy="10.16.17.12" + mmsport="8888" + mmsc="http://mms" + authtype="1" + type="mms" + /> + + <apn carrier="Personal Datos Py" + carrier_id = "1928" + mcc="744" + mnc="05" + apn="internet" + user="personal" + password="personal" + authtype="1" + type="default,supl" + /> + + <apn carrier="Personal MMS Py" + carrier_id = "1928" + mcc="744" + mnc="05" + apn="mms" + user="mms" + password="mms" + mmsproxy="172.16.192.7" + mmsport="8080" + mmsc="http://mms" + authtype="1" + type="mms" + /> + + <apn carrier="Telesur" + carrier_id = "1083" + mcc="746" + mnc="02" + apn="default" + type="default,supl" + /> + + <apn carrier='Suriname:Digicel:Internet' + carrier_id = "1084" + mcc='746' + mnc='03' + apn='web.digicelsr.com' + authtype='1' + type='default' + /> + + <apn carrier='Suriname:Digicel:Mms' + carrier_id = "1084" + mcc='746' + mnc='03' + apn='wap.digicelsr.com' + authtype='1' + mmsc='http://mmc.digicelsr.com/servlets/mms' + mmsproxy='172.20.6.12' + mmsport='9201' + type='mms' + user='wap' + password='wap' + /> + + <apn carrier='Suriname:Digicel:Modem' + carrier_id = "1084" + mcc='746' + mnc='03' + apn='wap.digicelsr.com' + port='8080' + authtype='1' + proxy='172.20.6.12' + mmsc='http://wapdigicel.com' + type='dun' + user='wap' + password='wap' + /> + + <apn carrier="wapANCEL" + carrier_id = "1862" + mcc="748" + mnc="01" + apn="wap" + proxy="200.40.246.2" + port="3128" + user="" + password="" + authtype="1" + type="default,supl" + /> + + <apn carrier="mmsANCEL" + carrier_id = "1862" + mcc="748" + mnc="01" + apn="mms" + user="" + password="" + mmsproxy="200.40.246.2" + mmsport="3128" + mmsc="http://mmsc.mms.ancelutil.com.uy" + authtype="1" + type="mms" + /> + + <apn carrier="gprsANCEL" + carrier_id = "1862" + mcc="748" + mnc="01" + apn="gprs.ancel" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar INTERNET" + carrier_id = "1863" + mcc="748" + mnc="07" + apn="webapn.movistar.com.uy" + user="movistar" + password="movistar" + authtype="1" + type="default,supl" + /> + + <apn carrier="Movistar MMS" + carrier_id = "1863" + mcc="748" + mnc="07" + apn="apnmms.movistar.com.uy" + user="mmsuy" + password="mmsuy" + mmsproxy="10.0.2.29" + mmsport="8080" + mmsc="http://mmsc.movistar.com.uy" + authtype="1" + type="mms" + /> + + <apn carrier="Claro UY" + carrier_id = "1864" + mcc="748" + mnc="10" + apn="igprs.claro.com.uy" + user="ctigprs" + password="ctigprs999" + authtype="1" + type="default,supl" + /> + + <apn carrier="MMS GPRS UY" + carrier_id = "1864" + mcc="748" + mnc="10" + apn="mms.ctimovil.com.uy" + user="ctimms" + password="ctimms999" + mmsproxy="170.51.255.240" + mmsport="8080" + mmsc="http://mms.ctimovil.com.uy" + authtype="1" + type="mms" + /> + + <apn carrier="Orange Armenia MMS" + carrier_id = "1940" + mcc="283" + mnc="10" + apn="mms" + mmsc="http://mms/" + mmsproxy="192.168.220.251" + mmsport="3128" + type="mms" + authtype="1" + /> + + <apn carrier="Orange Armenia Internet" + carrier_id = "1940" + mcc="283" + mnc="10" + apn="Internet" + type="default" + authtype="1" + /> + + <apn carrier="Orange BW MMS" + carrier_id = "567" + mcc="652" + mnc="02" + apn="mms.orange.co.bw" + mmsc="http://10.0.0.242/servlets/mms" + mmsproxy="10.0.0.226" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange WAP BW" + carrier_id = "567" + mcc="652" + mnc="02" + apn="internet.orange.co.bw" + proxy="10.0.0.226" + port="8080" + type="default" + /> + + <apn carrier="Orange CM" + carrier_id = "1434" + mcc="624" + mnc="02" + apn="orangecmgprs" + user="orange" + password="orange" + proxy="192.168.122.101" + port="8080" + mmsc="http://mms.orange.cm" + mmsproxy="192.168.122.101" + mmsport="8080" + type="default,mms" + /> + + <apn carrier="Orange net KE" + carrier_id = "2210" + mcc="639" + mnc="07" + apn="bew.orange.co.ke" + type="default" + /> + + <apn carrier="Orange RE" + carrier_id = "1676" + mcc="647" + mnc="00" + apn="orangerun" + user="orange" + password="orange" + type="default" + /> + + <apn carrier="Orange MG MMS" + carrier_id = "1606" + mcc="646" + mnc="02" + apn="orangemms" + user="mms" + password="orange" + mmsc="http://10.152.10.70.38090" + mmsproxy="10.150.0.115" + mmsport="8080" + type="mms" + /> + + <apn carrier="Orange World MG" + carrier_id = "1606" + mcc="646" + mnc="02" + apn="orangeworld" + user="world" + password="orange" + proxy="10.150.0.115" + port="8080" + type="default" + /> + + <apn carrier="CIOT Vodafone" + mcc="901" + mnc="28" + apn="ciot.vodafone.com" + user="vodafone" + password="vodafone" + type="default" + /> + + <apn carrier="mobiledata" + mcc="901" + mnc="37" + apn="mobiledata" + type="default,supl" + /> + + <apn carrier="EMnify" + mcc="901" + mnc="43" + apn="em" + type="default,supl" + /> + + <apn carrier="BICS Internet" + carrier_id = "2132" + mcc="901" + mnc="58" + apn="bicsapn" + type="default,supl" + /> + + <apn carrier="Sberbank-Telecom Internet" + carrier_id = "2251" + mcc="250" + mnc="50" + apn="internet.sberbank-tele.com" + user="" + password="" + type="default,supl" + mvno_type="gid" + mvno_match_data="FA3207" + /> + <apn carrier="Sberbank-Telecom MMS" + carrier_id = "2251" + mcc="250" + mnc="50" + apn="mms.sberbank-tele.com" + user="" + password="" + mmsc="http://mmsc" + mmsproxy="10.77.36.100" + mmsport="8080" + type="mms" + mvno_type="gid" + mvno_match_data="FA3207" + /> + <apn carrier="Sberbank-Telecom IMS" + carrier_id = "2251" + mcc="250" + mnc="50" + apn="ims" + type="ims" + protocol="IPV4V6" + mvno_type="gid" + mvno_match_data="FA3207" + /> + + <apn carrier="Unleashed" + carrier_id = "2144" + mcc="206" + mnc="30" + apn="web.be" + type="default,supl" + /> + + <apn carrier="Kena Mobile Web" + mcc="222" + mnc="07" + apn="web.kenamobile.it" + type="default" + /> + + <apn carrier="Kena Mobile MMS" + mcc="222" + mnc="07" + apn="mms.kenamobile.it" + type="mms" + mmsc="http://mms.kenamobile.it" + mmsproxy="10.248.1.12" + mmsport="80" + /> + + <apn carrier="Lycamobile" + mcc="505" + mnc="19" + apn="data.lycamobile.com.au" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="242" + mnc="23" + apn="data.lyca-mobile.no" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="228" + mnc="54" + apn="data.lycamobile.ch" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + carrier_id = "2404" + mcc="232" + mnc="08" + apn="data.lycamobile.at" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="206" + mnc="06" + apn="data.lycamobile.be" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="262" + mnc="43" + apn="data.lycamobile.de" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="238" + mnc="12" + apn="data.lycamobile.dk" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="214" + mnc="25" + apn="data.lycamobile.es" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="208" + mnc="25" + apn="data.lycamobile.fr" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="272" + mnc="13" + apn="data.lycamobile.ie" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="204" + mnc="09" + apn="data.lycamobile.nl" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + carrier_id = "2403" + mcc="260" + mnc="09" + apn="data.lycamobile.pl" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="268" + mnc="04" + apn="data.lycamobile.pt" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="226" + mnc="16" + apn="data.lycamobile.ro" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + carrier_id = "2405" + mcc="240" + mnc="12" + apn="data.lycamobile.se" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="222" + mnc="35" + apn="data.lycamobile.it" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="311" + mnc="960" + apn="data.lycamobile.com" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="641" + mnc="26" + apn="data.lycamobile.ug" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="294" + mnc="04" + apn="data.lycamobile.mk" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Lycamobile" + mcc="655" + mnc="53" + apn="data.lycamobile.co.za" + authtype="1" + user="" + password="" + mvno_type="spn" + mvno_match_data="Lycamobile" + /> + + <apn carrier="Internet" + mcc="234" + mnc="57" + apn="mobile.sky" + authtype="0" + type="default,supl" + /> + + <apn carrier="MMS" + mcc="234" + mnc="57" + apn="mms.mobile.sky" + mmsc="http://185.110.178.96:38090/was" + mmsproxy="185.110.178.97" + mmsport="9028" + type="mms" + /> + + <apn carrier="Altan" + carrier_id = "2469" + mcc="334" + mnc="140" + apn="internet.altan" + type="default" + user="" + password="" + /> + + <apn carrier="Altan" + carrier_id = "2469" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + /> + + <apn carrier="IENTC" + carrier_id = "2470" + mcc="334" + mnc="140" + apn="internet.ientc.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="IENTC" + /> + + <apn carrier="NeWWW" + carrier_id = "2471" + mcc="334" + mnc="140" + apn="internet.newww.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="NeWWW" + /> + + <apn carrier="NeWWW" + carrier_id = "2471" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="NeWWW" + /> + + <apn carrier="travelfy" + carrier_id="2472" + apn="travelfy" + type="default,supl" + /> + + <apn carrier="Internet WOM" + carrier_id="1430" + mcc="730" + mnc="09" + apn="internet" + type="default" + user="" + password="" + protocol="IPV4V6" + roaming_protocol="IPV4V6" + user_editable="false" + /> + + <apn carrier="IMS" + carrier_id="1430" + mcc="730" + mnc="09" + apn="ims" + type="ims" + user="" + password="" + protocol="IPV4" + roaming_protocol="IPV4" + user_editable="false" + user_visible="false" + /> + + <apn carrier="Megacable" + carrier_id="2473" + mcc="334" + mnc="140" + apn="mega45g.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="Mega4.5 G" + /> + + <apn carrier="Megacable" + carrier_id="2473" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="Mega4.5 G" + /> + + <apn carrier="Netwey" + carrier_id="2474" + mcc="334" + mnc="140" + apn="internet.netwey.com.mx" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="NETWEY" + /> + + <apn carrier="Netwey" + carrier_id="2474" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="NETWEY" + /> + + <apn carrier="Retemex" + carrier_id="2475" + mcc="334" + mnc="140" + apn="internet.retemex.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="RETEMEX" + /> + + <apn carrier="Retemex" + carrier_id="2475" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="RETEMEX" + /> + + <apn carrier="Walmart MX" + carrier_id="2476" + mcc="334" + mnc="140" + apn="internet.wm.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="BAIT" + /> + + <apn carrier="Walmart MX" + carrier_id="2476" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="BAIT" + /> + + <apn carrier="Iusacomm" + carrier_id="2477" + mcc="334" + mnc="140" + apn="internet.iusacomm.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="IUSATEL" + /> + + <apn carrier="Iusacomm" + carrier_id="2477" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="IUSATEL" + /> + + <apn carrier="CFE" + carrier_id="2478" + mcc="334" + mnc="140" + apn="internet.cfe.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="CFE TEIPT" + /> + + <apn carrier="CFE" + carrier_id="2478" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="CFE TEIPT" + /> + + <apn carrier="Inten" + carrier_id="2479" + mcc="334" + mnc="140" + apn="internet.inten.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="INTEN" + /> + + <apn carrier="Inteni" + carrier_id="2479" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="INTEN" + /> + + <apn carrier="Diveracy" + carrier_id="2480" + mcc="334" + mnc="140" + apn="internet.diveracy.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="NEMI" + /> + + <apn carrier="Diveracy" + carrier_id="2480" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="NEMI" + /> + + <apn carrier="Diri" + carrier_id="2481" + mcc="334" + mnc="140" + apn="internet.diri.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="DIRI" + /> + + <apn carrier="Diri" + carrier_id="2481" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="DIRI" + /> + + <apn carrier="Topos" + carrier_id="2482" + mcc="334" + mnc="140" + apn="internet.turbored.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="TURBORED" + /> + + <apn carrier="Topos" + carrier_id="2482" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="TURBORED" + /> + + <apn carrier="Guruweb" + carrier_id="2483" + mcc="334" + mnc="140" + apn="internet.gugacom.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="Gurucomm" + /> + + <apn carrier="Guruweb" + carrier_id="2483" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="Gurucomm" + /> + + <apn carrier="Ubix" + carrier_id="2484" + mcc="334" + mnc="140" + apn="internet.ubix.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="Ubix" + /> + + <apn carrier="Ubix" + carrier_id="2484" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="Ubix" + /> + + <apn carrier="Rocketel" + carrier_id="2485" + mcc="334" + mnc="140" + apn="internet.rocketel.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="PagaPhone" + /> + + <apn carrier="Rocketel" + carrier_id="2485" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="PagaPhone" + /> + + <apn carrier="Redpotencia" + carrier_id="2486" + mcc="334" + mnc="140" + apn="internet.edilar.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="Redpotencia" + /> + + <apn carrier="Redpotencia" + carrier_id="2486" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="Redpotencia" + /> + + <apn carrier="Adinteli 1" + carrier_id="2487" + mcc="334" + mnc="140" + apn="internet.plus.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="CHAMO-MOVIL" + /> + + <apn carrier="Adinteli 1" + carrier_id="2487" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="CHAMO-MOVIL" + /> + + <apn carrier="Adinteli 2" + carrier_id="2487" + mcc="334" + mnc="140" + apn="internet.plus.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="BYPLUS" + /> + + <apn carrier="Adinteli 2" + carrier_id="2487" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="BYPLUS" + /> + + <apn carrier="Izzi" + carrier_id="2488" + mcc="334" + mnc="140" + apn="internet.izzi.mx" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="izzi" + /> + + <apn carrier="Izzi" + carrier_id="2488" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="izzi" + /> + + <apn carrier="Adm" + carrier_id="2489" + mcc="334" + mnc="140" + apn="internet.adm.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="MISTRAL" + /> + + <apn carrier="Adm" + carrier_id="2489" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="MISTRAL" + /> + + <apn carrier="Ads" + carrier_id="2490" + mcc="334" + mnc="140" + apn="internet.mexfon.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="MEXFON" + /> + + <apn carrier="Ads" + carrier_id="2490" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="MEXFON" + /> + + <apn carrier="Yonder" + carrier_id="2491" + mcc="334" + mnc="140" + apn="internet.yotelco.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="YO" + /> + + <apn carrier="Yonder" + carrier_id="2491" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="YO" + /> + + <apn carrier="Arlonet" + carrier_id="2492" + mcc="334" + mnc="140" + apn="internet.arloesinet.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="Arlonet" + /> + + <apn carrier="Arlonet" + carrier_id="2492" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="Arlonet" + /> + + <apn carrier="Tridex" + carrier_id="2493" + mcc="334" + mnc="140" + apn="internet.valor.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="VALOR" + /> + + <apn carrier="Tridex" + carrier_id="2493" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="VALOR" + /> + + <apn carrier="Wimo" + carrier_id="2494" + mcc="334" + mnc="140" + apn="internet.wimo.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="WiMO" + /> + + <apn carrier="Wimoi" + carrier_id="2494" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="WiMO" + /> + + <apn carrier="Oui" + carrier_id="2495" + mcc="334" + mnc="140" + apn="internet.oui.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="OUI" + /> + + <apn carrier="Oui" + carrier_id="2495" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="OUI" + /> + + <apn carrier="Freedompop" + carrier_id="2496" + mcc="334" + mnc="140" + apn="Internet.mvne1.com" + type="default" + user="" + password="" + mvno_type="spn" + mvno_match_data="FreedomPop" + /> + + <apn carrier="Freedompop" + carrier_id="2496" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="FreedomPop" + /> + + <apn carrier="IENTC" + carrier_id = "2470" + mcc="334" + mnc="140" + apn="ims" + type="ims" + user="" + password="" + mvno_type="spn" + mvno_match_data="IENTC" + /> +</apns> diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/call-pppd b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/call-pppd new file mode 100755 index 0000000..9f7f1cb --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/call-pppd @@ -0,0 +1,34 @@ +#!/system/bin/sh +# An unforunate wrapper script +# so that the exit code of pppd may be retrieved + + +#PPPD_PID="" +PPPD_EXIT="" + +/system/bin/setprop "net.gprs.ppp-exit" "" + +/system/bin/log -t pppd "Starting pppd" + +/system/bin/log -t pppd "PARAM1: $1" +/system/bin/log -t pppd "PARAM2: $2" +/system/bin/log -t pppd "PARAM3: $3" +/system/bin/log -t pppd "PARAM4: $4" +/system/bin/log -t pppd "PARAM5: $5" + +if [ $# -lt 6 ] ; then + +/system/bin/pppd $1 debug defaultroute noauth nodetach nocrtscts novj noipdefault usepeerdns user "$2" password "$3" connect "$4" disconnect "$5" + +else + +/system/bin/log -t pppd "PARAM6: $6" +/system/bin/pppd $1 debug defaultroute noauth nodetach nocrtscts $2 noipdefault usepeerdns user "$3" password "$4" connect "$5" disconnect "$6" +fi +PPPD_EXIT=$? +#PPPD_PID=$! + +#/system/bin/log -t pppd "pppd pid: $PPPD_PID" +/system/bin/log -t pppd "pppd exited with $PPPD_EXIT" + +/system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT" diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/chat b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/chat new file mode 100755 index 0000000..69ae636 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/chat Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/dhcpcd b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/dhcpcd new file mode 100755 index 0000000..b6c23ea --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/dhcpcd Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-down b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-down new file mode 100755 index 0000000..40ffdbe --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-down Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-up b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-up new file mode 100755 index 0000000..6aa7702 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ip-up Binary files differ diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ql-ril.conf b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ql-ril.conf new file mode 100755 index 0000000..6591d53 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/bin64/ql-ril.conf @@ -0,0 +1,42 @@ +#This file is in a state of unavailability. +#In most cases, there is no need to open any option. +#In special cases, please use it under the guidance of FAE. + +#LTE_SignalStrength=-1 +#LTE_Is_Report_SignalStrength=1 +#At_Cmds_For_Customer_Initialize=at+csq;at+cgreg?;at+cops?;at+qcfg="nwscanmodeex" +#Icc_Constants=EF_ICCID +#support_CDMPhone=1 +#URC_delay_mseconds=2000 +#Query_Available_Networks=1 +#Sim_Hot_Plugging=1 #0-not support; 1-support low level; 2-support high level +#at_qcrmcall=1 +#Recovery_App= +#ATT_Test=1 +#need_switch_CMT_to_CMTI=1 +#RevokeClientIDIndication=1 +#PS_ONLY=1 +#check_data_stall=1 +#POLL_CALL_STATE=1 +#support_fota=1 #url and local path should start with 'fota:'. such as 'fota:/data/EC200Txxxxxxx.bin' +#autoUnlockPin=1 +#check_sms_manually=1 +#support_x55_loopback=1 +#manifest_path=/odm/etc/vintf/xxx.xml #xxx.xml is the name of manifest,such as manifest_m50_nonpayment_cell.xml +#usb_port_path1= +#usb_port_path2= +#use_dsda=1 +#RIL_REQUEST_SHUTDOWN_SUPPORT=0 +#RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE_SUPPORT=0 +#RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL_SUPPORT=0 +#RM500Voice=1 +#SetPreferredNetworkType_NR=1 +#asr_support_gps=1 +#IPv4v6_was_also_successful=1 +#usbnet=mbim +#not_support_0b00=1 +#ue_function_mode=1 #1 data only 2 data voice 3 data_voice_roaming 4 voice only +#active_query_network_resident=1 +#asr_zhanrui_support_ipv6=1 +#plane_mode_0=1 +#use_MTK=1 diff --git a/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/manifest.xml b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/manifest.xml new file mode 100755 index 0000000..866b401 --- /dev/null +++ b/android/vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/manifest.xml @@ -0,0 +1,12 @@ +<manifest version="1.0" type="device" target-level="4"> + <hal format="hidl"> + <name>android.hardware.radio</name> + <transport>hwbinder</transport> + <version>1.4</version> + <interface> + <name>IRadio</name> + <instance>slot1</instance> + </interface> + <fqname>@1.2::ISap/slot1</fqname> + </hal> +</manifest> diff --git a/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk b/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk old mode 100644 new mode 100755 index e204028..2403104 --- a/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk +++ b/android/vendor/aw/public/prebuild/lib/librild/radio_common.mk @@ -1,38 +1,128 @@ LOCAL_PATH := vendor/aw/public/prebuild/lib/librild -RIL_LIB_VERSION ?= 10.0 +RIL_LIB_VERSION ?= 12.0 RIL_LIB_BASENAME ?= libsoftwinner-ril-$(RIL_LIB_VERSION) # 3G Data Card Packages PRODUCT_PACKAGES += \ - android.hardware.radio@1.4 \ - android.hardware.radio.config@1.1-service \ - android.hardware.radio.config@1.1 \ + CarrierDefaultApp \ + CarrierConfig \ pppd_vendor \ rild \ chat \ - $(RIL_LIB_BASENAME) \ + dhcpcd \ + libreference-ril-an12 \ + libreference-ril-an10 \ radio_monitor -DISABLE_RILD_OEM_HOOK := true +#PRODUCT_PACKAGES += \ + android.hardware.radio@1.5-radio-service \ + android.hardware.radio.config@1.2-service \ + android.hardware.radio.config@1.0-service \ + android.hardware.radio@1.5 + +PRODUCT_PACKAGES += \ + android.hardware.radio@1.4 \ + android.hardware.radio.config@1.1-service \ + android.hardware.radio.config@1.1 \ + +#PRODUCT_PACKAGES += \ + android.hardware.radio@1.2-radio-service \ + +#PRODUCT_PACKAGES += \ + android.hardware.radio@1.0-radio-service \ + android.hardware.radio@1.1-radio-service \ + android.hardware.radio@1.2-radio-service \ + android.hardware.radio@1.3-radio-service \ + android.hardware.radio@1.4-radio-service \ + android.hardware.radio@1.5-radio-service \ + android.hardware.radio@1.6-radio-service + +#PRODUCT_PACKAGES += \ + android.hardware.radio@1.0 \ + android.hardware.radio@1.1 \ + android.hardware.radio@1.2 \ + android.hardware.radio@1.3 \ + android.hardware.radio@1.4 \ + android.hardware.radio@1.5 \ + android.hardware.radio@1.6 + +#PRODUCT_PACKAGES += \ + android.hardware.radio.config@1.0 \ + android.hardware.radio.config@1.1 \ + android.hardware.radio.config@1.2 \ + android.hardware.radio.config@1.3 + +#PRODUCT_PACKAGES += \ + android.hardware.radio.config@1.1-service \ + android.hardware.radio.config@1.2-service \ + android.hardware.radio.config@1.3-service + +# DISABLE_RILD_OEM_HOOK := true # 3G Data Card Configuration Flie -PRODUCT_COPY_FILES += \ - $(LOCAL_PATH)/config/data_call/ip-down:$(TARGET_COPY_OUT_VENDOR)/bin/etc/ppp/ip-down \ - $(LOCAL_PATH)/config/data_call/ip-up:$(TARGET_COPY_OUT_VENDOR)/bin/etc/ppp/ip-up \ - $(LOCAL_PATH)/config/data_call/3g_dongle.cfg:$(TARGET_COPY_OUT_VENDOR)/etc/3g_dongle.cfg \ - $(LOCAL_PATH)/config/data_call/apns-conf_sdk.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml \ +# PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/config/initrc/env.librild.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/env.librild.rc +# $(LOCAL_PATH)/config/data_call/ip-down:$(TARGET_COPY_OUT_VENDOR)/bin/etc/ppp/ip-down \ +# $(LOCAL_PATH)/config/data_call/ip-up:$(TARGET_COPY_OUT_VENDOR)/bin/etc/ppp/ip-up \ +# $(LOCAL_PATH)/config/data_call/3g_dongle.cfg:$(TARGET_COPY_OUT_VENDOR)/etc/3g_dongle.cfg \ +# $(LOCAL_PATH)/config/data_call/apns-conf_sdk.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml \ + +PRODUCT_PACKAGES += \ + usb_dongle + # Radio Monitor Configuration Flie -PRODUCT_COPY_FILES += \ - $(LOCAL_PATH)/config/radio_monitor/usb_modeswitch:$(TARGET_COPY_OUT_VENDOR)/bin/usb_modeswitch \ - $(call find-copy-subdir-files,*,$(LOCAL_PATH)/config/radio_monitor/usb_modeswitch.d,$(TARGET_COPY_OUT_VENDOR)/etc/usb_modeswitch.d) +PRODUCT_PACKAGES += usb_modeswitch +# PRODUCT_COPY_FILES += \ +# $(call find-copy-subdir-files,*,$(LOCAL_PATH)/config/radio_monitor/usb_modeswitch.d,$(TARGET_COPY_OUT_VENDOR)/etc/usb_modeswitch.d) +# #$(LOCAL_PATH)/config/radio_monitor/usb_modeswitch:$(TARGET_COPY_OUT_VENDOR)/bin/usb_modeswitch \ # Radio parameter PRODUCT_PROPERTY_OVERRIDES += \ vendor.rild.libargs=-d/dev/ttyUSB2 \ - vendor.rild.libpath=$(RIL_LIB_BASENAME).so \ - ro.radio.noril=true \ + ro.radio.noril=false \ ro.radio.noawril=false \ ro.vendor.sw.embeded.telephony=false + +PRODUCT_PROPERTY_OVERRIDES += \ + vendor.rild.libpath=/vendor/lib64/libreference-ril-an10.so + +PRODUCT_PROPERTY_OVERRIDES += \ + ro.telephony.default_network=9 \ + persist.sys.pref.net.type=10 \ + rild.libargs=-d/dev/ttyUSB2 \ + ro.com.android.mobiledata=true \ + ro.com.android.prov_mobiledata=true + +PRODUCT_PACKAGES += \ + Telecom \ + TeleService \ + Telephony \ + TelephonyProvider + +PRODUCT_PACKAGES += \ + Mms \ + ContactsCommon \ + libril3 \ + rild3 \ + Stk \ + ip-up \ + ip-down \ + libril \ + librilutils + +PRODUCT_COPY_FILES += $(LOCAL_PATH)/quecte_ec20_modem/apns-full-conf.xml:$(TARGET_COPY_OUT_PRODUCT)/etc/apns-conf.xml + +DEVICE_MANIFEST_FILE += vendor/aw/public/prebuild/lib/librild/quecte_ec20_modem/manifest.xml + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/call-pppd:$(TARGET_COPY_OUT_SYSTEM)/etc/ppp/call-pppd \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/ip-down:$(TARGET_COPY_OUT_SYSTEM)/etc/ppp/ip-down \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/ip-up:$(TARGET_COPY_OUT_SYSTEM)/etc/ppp/ip-up \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/ql-ril.conf:$(TARGET_COPY_OUT_VENDOR)/etc/ql-ril.conf + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/dhcpcd:$(TARGET_COPY_OUT_VENDOR)/bin/dhcpcd \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/call-pppd:$(TARGET_COPY_OUT_SYSTEM)/etc/ppp/call-pppd \ + $(LOCAL_PATH)/quecte_ec20_modem/bin64/chat:$(TARGET_COPY_OUT_SYSTEM)/bin/chat diff --git a/longan/kernel/linux-4.9/drivers/usb/serial/option.c b/longan/kernel/linux-4.9/drivers/usb/serial/option.c index 665f417..12d06a1 100644 --- a/longan/kernel/linux-4.9/drivers/usb/serial/option.c +++ b/longan/kernel/linux-4.9/drivers/usb/serial/option.c @@ -1970,7 +1970,8 @@ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ .driver_info = RSVD(6) }, #if 1 - { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */ + { USB_DEVICE(0x2C7C, 0x6002) }, /* Quectel EC200 */ + { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */ { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */ { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25/EC20 R2.0 */ { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */ -- Gitblit v1.6.2