├── .gitignore ├── HACKING.md ├── Makefile ├── README.md ├── busybox ├── c_stubs │ └── missing_functions.c ├── editors │ └── awk.c ├── include │ ├── libbb.h │ └── xregex.h └── libbb │ ├── copyfd.c │ ├── full_write.c │ ├── getopt32.c │ ├── llist.c │ ├── messages.c │ ├── perror_msg.c │ ├── platform.c │ ├── process_escape_sequence.c │ ├── read.c │ ├── safe_write.c │ ├── skip_whitespace.c │ ├── verror_msg.c │ ├── wfopen.c │ ├── wfopen_input.c │ ├── xatonum.c │ ├── xatonum_template.c │ ├── xfunc_die.c │ ├── xfuncs.c │ ├── xfuncs_printf.c │ └── xregcomp.c ├── js_emsc ├── post_AWK.js ├── post_AWK_web_worker.js ├── pre_AWK.js └── pre_AWK_web_worker.js ├── newlib └── libc │ ├── posix │ ├── cclass.h │ ├── cname.h │ ├── collate.c │ ├── collate.h │ ├── collcmp.c │ ├── engine.c │ ├── namespace.h │ ├── regcomp.c │ ├── regerror.c │ ├── regex.h │ ├── regex2.h │ ├── regexec.c │ ├── regfree.c │ ├── rune.h │ ├── un-namespace.h │ └── utils.h │ └── stdlib │ ├── getopt.c │ └── getopt.h ├── prebuilt ├── awk_node.js.gz └── awk_web.js.gz ├── tests ├── my_input.txt ├── my_program.awk └── web_test.js └── website ├── awk_web.html └── awk_web_worker.html /.gitignore: -------------------------------------------------------------------------------- 1 | README.html 2 | 3 | awk_node.js 4 | website/awk_web.js 5 | website/awk_web_worker.js 6 | awk_bin 7 | tmp_web_test.js 8 | test.html 9 | -------------------------------------------------------------------------------- /HACKING.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting emscripten related problems: 2 | 3 | 1. first thing to try, is reduce optimization to -O0 (see Makefile). 4 | 2. Try -O1 5 | 3. Then "-O2 --closure 0 --minify 0" 6 | 4. Then enable closure (but not minification) - helps to see if how the code is closured/minified. Also see: https://github.com/kripken/emscripten/issues/704 7 | 8 | 9 | # Debugging the AWK program or adding functionality 10 | 11 | 1. run `make bin` and `make bin-test` to run the AWK program as a native binary executable. 12 | 2. Try running the same AWK script with GNU AWK, and with BusyBox's AWK - to pinpoint if the bug is related to the changes made in this project. 13 | 3. GDB can debug the `awk_bin` file easily. 14 | 15 | 16 | # Following AWK progress 17 | 1. Enable "NODE_JS_DEBUG" in ./busybox/include/libbb.h to see some progress messages. Add more and re-compile if needed: 18 | ```node_js_debug("something is wrong, i=%d\n", i);``` 19 | 20 | Will work in the binary version, node.js version and web version. 21 | 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | EMCC=emcc 3 | # if 'emcc' (the emscripten compiler) is not in your $PATH, 4 | # set the full path here: 5 | #EMCC=~/sources/emscripten/emcc 6 | 7 | NEWLIB_SRC=newlib/libc/posix/regerror.c \ 8 | newlib/libc/posix/regfree.c \ 9 | newlib/libc/posix/regcomp.c \ 10 | newlib/libc/posix/collcmp.c \ 11 | newlib/libc/posix/collate.c \ 12 | newlib/libc/posix/regexec.c \ 13 | newlib/libc/stdlib/getopt.c 14 | 15 | 16 | BUSYBOX_AWK_SRC=busybox/editors/awk.c \ 17 | busybox/libbb/wfopen_input.c \ 18 | busybox/libbb/skip_whitespace.c \ 19 | busybox/libbb/llist.c \ 20 | busybox/libbb/wfopen.c \ 21 | busybox/libbb/xfuncs_printf.c \ 22 | busybox/libbb/xfuncs.c \ 23 | busybox/libbb/messages.c \ 24 | busybox/libbb/verror_msg.c \ 25 | busybox/libbb/process_escape_sequence.c \ 26 | busybox/libbb/perror_msg.c \ 27 | busybox/libbb/read.c \ 28 | busybox/libbb/xfunc_die.c \ 29 | busybox/libbb/full_write.c \ 30 | busybox/libbb/copyfd.c \ 31 | busybox/libbb/safe_write.c \ 32 | busybox/libbb/platform.c \ 33 | busybox/libbb/getopt32.c \ 34 | busybox/libbb/xregcomp.c \ 35 | busybox/libbb/xatonum.c \ 36 | busybox/c_stubs/missing_functions.c 37 | 38 | BUSYBOX_INCLUDE_PATH=-Ibusybox/include -Inewlib/libc/posix -Inewlib/libc/stdlib 39 | 40 | OPT_FLAGS=-O2 --closure 1 --minify 1 41 | #OPT_FLAGS=-O0 42 | 43 | JS_FLAGS=-s WARN_ON_UNDEFINED_SYMBOLS=1 \ 44 | -s CATCH_EXIT_CODE=1 45 | 46 | PRE_JS_SRC=js_emsc/pre_AWK.js 47 | POST_JS_SRC=js_emsc/post_AWK.js 48 | 49 | PRE_JS_WEBWORKER_SRC=js_emsc/pre_AWK_web_worker.js 50 | POST_JS_WEBWORKER_SRC=js_emsc/post_AWK_web_worker.js 51 | 52 | .PHONY: all 53 | all: 54 | oo-all: 55 | @echo 56 | @echo "WebAWK - AWK in Javascript" 57 | @echo " https://github.com/agordon/webawk.git" 58 | @echo "" 59 | @echo " See README.md for more details" 60 | @echo "" 61 | @echo "Possible targets:" 62 | @echo " make bin - Compile native binary using CLANG for debugging (awk_bin)" 63 | @echo " make bin-test - test the binary version" 64 | @echo " make node - Compile the node version (awk_node.js)" 65 | @echo " make node-test - test the AWK node version" 66 | @echo " make web - Compile the web version (website/awk_web.js)" 67 | @echo " make web-test - Print the URL to test the web version" 68 | @echo " make webworker - Compile the web-worker version (website/awk_web_worker.js)" 69 | @echo " make webworker-test - Print the URL to test the web version" 70 | @echo "" 71 | @echo " make prebuilt - If you don't have llvm/clang/emscripten compilers" 72 | @echo " installed, use the pre-built javascript versions." 73 | @echo " run this target if you want to experiment with WebAWK" 74 | @echo " without compiling." 75 | @echo " make clean - delete the compiled javascript files." 76 | @echo "" 77 | @echo "" 78 | 79 | .PHONY: check_emcc 80 | check_emcc: 81 | @(if ! which "$(EMCC)" > /dev/null ; then \ 82 | echo "" >&2 ; \ 83 | echo "Error: can't find EMCC compiler (looking for '$(EMCC)')." >&2 ; \ 84 | echo "" >&2 ; \ 85 | echo "If you have EMCC installed, please add it to your PATH," >&2 ; \ 86 | echo " or change the 'EMCC=' directive in this Makefile." >&2 ; \ 87 | echo "" >&2 ; \ 88 | echo "If you don't have EMCC installed, you can run 'make prebuilt'" >&2 ; \ 89 | echo " to use the pre-built javascript versions." >&2 ; \ 90 | exit 1 ; \ 91 | fi ) 92 | 93 | 94 | .PHONY: web 95 | web: website/awk_web.js 96 | 97 | website/awk_web.js: $(BUSYBOX_AWK_SRC) $(NEWLIB_SRC) $(PRE_JS_SRC) $(POST_JS_SRC) 98 | $(EMCC) $(OPT_FLAGS) $(JS_FLAGS) \ 99 | $(BUSYBOX_INCLUDE_PATH) \ 100 | -DWEBAWK_CALLBACK_CUSTOM \ 101 | $(BUSYBOX_AWK_SRC) \ 102 | $(NEWLIB_SRC) \ 103 | --pre-js $(PRE_JS_SRC) \ 104 | --post-js $(POST_JS_SRC) \ 105 | -o $@ 106 | 107 | # Undocumented target: 108 | # create a Javascript+HTML stub for direct loading, 109 | # skipping the custom pre/post javascripts. 110 | # try this if you suspect a bug in the pre/post files. 111 | test.html: check_emcc $(BUSYBOX_AWK_SRC) $(NEWLIB_SRC) 112 | $(EMCC) $(OPT_FLAGS) $(JS_FLAGS) \ 113 | $(BUSYBOX_INCLUDE_PATH) \ 114 | $(BUSYBOX_AWK_SRC) \ 115 | $(NEWLIB_SRC) \ 116 | -o $@ 117 | 118 | .PHONY: web-test 119 | web-test: website/awk_web.js tests/web_test.js 120 | @cat website/awk_web.js tests/web_test.js > tmp_web_test.js 121 | @echo 122 | @echo "Simulating a web-browser call to 'run_web_awk()':" 123 | @echo 124 | node tmp_web_test.js 125 | @echo 126 | @echo 127 | @echo 128 | @echo "To test on in your web browser, load the following file:" 129 | @echo " file://$(PWD)/website/awk_web.html" 130 | @echo 131 | @echo 132 | @rm -f tmp_web_test.js 133 | 134 | .PHONY: webworker 135 | webworker: website/awk_web_worker.js 136 | 137 | ## NOTE: no closure optimization for webworkers - it doesn't work 138 | website/awk_web_worker.js: $(BUSYBOX_AWK_SRC) $(NEWLIB_SRC) $(PRE_JS_WEBWORKER_SRC) $(POST_JS_WEBWORKER_SRC) 139 | $(EMCC) $(JS_FLAGS) \ 140 | $(BUSYBOX_INCLUDE_PATH) \ 141 | -DWEBAWK_CALLBACK_CUSTOM \ 142 | $(BUSYBOX_AWK_SRC) \ 143 | $(NEWLIB_SRC) \ 144 | --pre-js $(PRE_JS_WEBWORKER_SRC) \ 145 | --post-js $(POST_JS_WEBWORKER_SRC) \ 146 | -o $@ 147 | 148 | .PHONY: webworker-test 149 | webworker-test: website/awk_web_worker.js 150 | @echo 151 | @echo 152 | @echo "Web-Workers can't be loaded using file:///" 153 | @echo " You must setup a local webserver for this directory:" 154 | @echo " $(PWD)/website" 155 | @echo 156 | @echo 157 | 158 | .PHONY: node 159 | node: awk_node.js 160 | 161 | # The node target embeds the two test input files 162 | # in the jvascript (there's no easy filesystem access from the node script) 163 | awk_node.js: check_emcc $(BUSYBOX_AWK_SRC) $(NEWLIB_SRC) 164 | $(EMCC) $(OPT_FLAGS) $(JS_FLAGS) \ 165 | -DWEBAWK_CALLBACK_CONSOLE \ 166 | $(BUSYBOX_INCLUDE_PATH) \ 167 | $(BUSYBOX_AWK_SRC) \ 168 | $(NEWLIB_SRC) \ 169 | --embed-file tests/my_program.awk \ 170 | --embed-file tests/my_input.txt \ 171 | -o $@ 172 | 173 | ## Important node about the node test: 174 | ## The AWK program will NOT read the actual input files (e.g. "tests/my_program.awk"). 175 | ## It will read the previously embedded files, from the Javascript. 176 | ## (see the --embed-file command in the compilation stage) 177 | .PHONY: node-test 178 | node-test: 179 | @echo 180 | @echo "Running Javascript/AWK parser using node ." 181 | @echo " You should see an \"Hello World\" message below:" 182 | @echo 183 | node awk_node.js 'BEGIN { print "Hello from Javascript/AWK" ; exit }' 184 | @echo 185 | @echo Second test: reading from input file 186 | @echo 187 | node awk_node.js -f tests/my_program.awk tests/my_input.txt 188 | @echo 189 | @echo 190 | @echo 191 | 192 | 193 | .PHONY: bin 194 | bin: awk_bin 195 | 196 | awk_bin: $(BUSYBOX_AWK_SRC) $(NEWLIB_SRC) 197 | clang -O0 -g \ 198 | $(BUSYBOX_INCLUDE_PATH) \ 199 | $(BUSYBOX_AWK_SRC) \ 200 | $(NEWLIB_SRC) \ 201 | -o $@ 202 | 203 | # Quick and dirty test to check the native-compiled busybox awk 204 | .PHONY: bin-test 205 | bin-test: awk_bin 206 | @echo 207 | @echo "Running AWK binary." 208 | @echo " You should see an \"Hello World\" message below:" 209 | @echo 210 | printf "1 A\n2 B\n3 C\n" | ./awk_bin 'BEGIN { print "Hello Busybox/AWK/Clang World" } $$1 ~ /2/ { print $$2 }' 211 | @echo 212 | @echo Second test: reading from input file 213 | @echo 214 | ./awk_bin -f tests/my_program.awk tests/my_input.txt 215 | @echo 216 | @echo 217 | @echo 218 | 219 | 220 | 221 | .PHONY: clean 222 | clean: clean-node clean-web clean-bin clean-webworker 223 | 224 | 225 | .PHONY: clean-node 226 | clean-node: 227 | rm -f awk_node.js 228 | 229 | .PHONY: clean-web 230 | clean-web: 231 | rm -f website/awk_web.js 232 | 233 | .PHONY: clean-webworker 234 | clean-webworker: 235 | rm -f website/awk_web_worker.js 236 | 237 | .PHONY: clean-bin 238 | clean-bin: 239 | rm -f awk_bin 240 | 241 | 242 | 243 | .PHONY: prebuilt 244 | prebuilt: 245 | @echo "copying pre-built javascript files..." 246 | @gunzip -dc prebuilt/awk_node.js.gz > awk_node.js 247 | @gunzip -dc prebuilt/awk_web.js.gz > website/awk_web.js 248 | @echo "Done." 249 | @echo 250 | @echo "Try testing the prebuilt files with:" 251 | @echo " make node-test" 252 | @echo " make web-test" 253 | @echo "" 254 | 255 | 256 | .PHONY: buildpre 257 | buildpre: node web 258 | @echo "storing new pre-built javascript files..." 259 | @gzip -c awk_node.js > prebuilt/awk_node.js.gz 260 | @gzip -c website/awk_web.js > prebuilt/awk_web.js.gz 261 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WebAWK - AWK in Javascript 2 | ================= 3 | 4 | This is an adaptation of the [AWK](http://en.wikipedia.org/wiki/AWK) programming language 5 | running entirely in Javascript, on the client-side web-browse (or on node.js). 6 | 7 | *NOTE* 8 | This is not a re-implementation of AWK in Javascript. 9 | The C source code of [Busybox AWK](http://www.busybox.net/) was compiled (slightly modified) using [emscripten](http://emscripten.org/) (a LLVM-to-Javascript compiler). 10 | 11 | 12 | Using WebAWK 13 | ------------ 14 | 15 | Online demo: http://agordon.github.com/webawk/ 16 | Interactive AWK demo (requires a recent web-browser): http://agordon.github.com/webawk/awk_web_worker.html 17 | 18 | Try locally: 19 | 20 | # download the code. 21 | $ git clone git://github.com/agordon/webawk.git 22 | $ cd webawk 23 | 24 | # use the supplied pre-built javascripts, to save time and effort. 25 | $ make prebuilt 26 | 27 | # test the node.js version 28 | # (need to have "node" installed, obviously) 29 | $ make node-test 30 | 31 | # test the web version 32 | # (this will print the URL of the file you'll need to open in your browser) 33 | $ make web-test 34 | 35 | # or build the javascripts, by compiling the C code. 36 | # see compilation instructions below. 37 | $ make node 38 | $ make web 39 | 40 | # To debug / add features, compile for a native binary 41 | $ make bin 42 | $ make bin-test 43 | 44 | 45 | Re-building the Javascript code 46 | ------------------------------- 47 | 48 | To rebuild the javascript code, you'll need the `clang` and the `emscripten` compilers. 49 | Follow the ([emscripten Tutorial](https://github.com/kripken/emscripten/wiki/Tutorial) for installation and testing instructions. 50 | 51 | **node.js version** 52 | 53 | * To compile the *node.js version*, run ```make node``` . 54 | * The *node.js version* is configured to start immediately (i.e. calling AWK's `main()` function). 55 | * The fcompiled output file is `awk_node.js`, and using it with node should be equivalent to running `awk` on the command line (note: equivalent to the old oawk, not GNU awk). 56 | * Try the following (which are equivalent to `make node-test`): 57 | 58 | ``` 59 | $ node awk_node.js 'BEGIN { print "Hello Node Awk World" ; exit }' 60 | vs. 61 | $ awk 'BEGIN { print "Hello Awk World" ; exit }' 62 | 63 | or 64 | 65 | $ node awk_node.js -f tests/my_program.awk tests/my_input.txt 66 | vs 67 | $ awk -f tests/my_program.awk tests/my_input.txt 68 | 69 | # Technical note: 70 | # the node version doesn't read the input files from 'tests' - 71 | # the files are embedded in the javascript during compilation 72 | # (so don't expect to change them and see the results) 73 | 74 | ``` 75 | 76 | 77 | **web version** 78 | 79 | * To compile the *web version*, run ```make web``` . 80 | * The compiled output file is `website/awk_web.js`. It contains the emscripten'd AWK code, wrapped in a single javascript function `run_web_awk()` . 81 | * Load the file `websize/awk_web.js` in your web-browser to run sample AWK programs. 82 | * The *web version* is configured with additional wrappers, and a friendly javascript function that runs awk on a given input. The source code for the wrappers is in `js_emsc` sub-directory. 83 | * See `tests/web_test.js` for an example of calling this function. 84 | 85 | 86 | **Compilation Warnings** 87 | 88 | Some warnings and error messages are expected when compiling with **emscripten**. 89 | 90 | Warnings similar to these can be ignored: 91 | 92 | ``` 93 | In file included from heirloom_emsc/libuxre/onefile.c:33: 94 | heirloom_emsc/libuxre/bracket.c:801:14: warning: array index of '1' indexes past the end of an array (that contains 1 element) 95 | [-Warray-bounds] 96 | mcbuf.wc = mcbuf.cep->weight[1]; 97 | ^ ~ 98 | heirloom_emsc/libuxre/colldata.h:163:2: note: array 'weight' declared here 99 | wuchar_type weight[COLL_WEIGHTS_MAX]; 100 | ^ 101 | In file included from heirloom_emsc/libuxre/onefile.c:37: 102 | heirloom_emsc/libuxre/regcomp.c:55:23: warning: '&&' within '||' [-Wlogical-op-parentheses] 103 | if (ep->re_nsub != 0 && (flags & (REG_NOSUB | REG_ONESUB)) == 0 104 | ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | heirloom_emsc/libuxre/regcomp.c:55:23: note: place parentheses around the '&&' expression to silence this warning 106 | if (ep->re_nsub != 0 && (flags & (REG_NOSUB | REG_ONESUB)) == 0 107 | ^ 108 | ``` 109 | 110 | Also, the following **unresolved symbols** are expected: 111 | 112 | ``` 113 | Warning: Unresolved symbol: _llvm_va_start 114 | Warning: Unresolved symbol: _llvm_dbg_declare 115 | Warning: Unresolved symbol: _llvm_expect_i32 116 | ``` 117 | 118 | However, if you get compilation errors, or other unresolved symbols - that's a likely problem that might prevent AWK from functioning. 119 | 120 | 121 | Compiling the AWK binary 122 | ------------------------ 123 | 124 | * To compile the *binry version*, run ```make bin``` (you'll need the `clang` compiler). 125 | * The compiled output file is `awk_bin`. 126 | * This file can be easily debugged with `gdb` (or similar debuggers). 127 | 128 | 129 | BusyBox AWK 130 | ----------- 131 | 132 | This awk implementation is based (=copied) from Busybox's AWK implementation, written by Dmitry Zakharov . It also uses many of the `libbb` functions. 133 | 134 | Website: http://www.busybox.net/ 135 | 136 | The code is based on Busybox version 1.20.2 . 137 | 138 | To see the changes, run: 139 | 140 | ``` 141 | $ git clone git://github.com/agordon/webawk.git 142 | $ wget http://www.busybox.net/downloads/busybox-1.20.2.tar.bz2 143 | $ tar -xjf busybox-1.20.2.tar.bz2 144 | $ diff -rup busybox-1.20.2/ weback/busybox 145 | ``` 146 | 147 | NEWLIB 148 | ------ 149 | 150 | This implementation uses the Posix Regular Expression code and the `getopt()` functions from RedHat's newlib. 151 | 152 | Website: http://sourceware.org/newlib/ 153 | 154 | The code is based on Newlib 1.20.0 . 155 | 156 | To see the changes, run: 157 | 158 | ``` 159 | $ git clone git://github.com/agordon/webawk.git 160 | $ wget ftp://sources.redhat.com/pub/newlib/newlib-1.20.0.tar.gz 161 | $ tar -xzf newline-1.20.0.tar.gz 162 | $ diff -rup newlib-1.20.0/newlib webawk/newlib 163 | ``` 164 | 165 | HACKING 166 | ------- 167 | 168 | See the `HACKING` file for more details. 169 | 170 | 171 | Contact 172 | ------- 173 | 174 | email: gordon at cshl dot edu 175 | source: https://github.com/agordon/webawk.git 176 | 177 | 178 | License 179 | ------- 180 | 181 | * The newlib `getopt` code is public domain. 182 | * The newlib `Regex` code is BSD. 183 | * The busybox code is GPLv2. 184 | * All other files are BSD. 185 | -------------------------------------------------------------------------------- /busybox/c_stubs/missing_functions.c: -------------------------------------------------------------------------------- 1 | #include "libbb.h" 2 | 3 | ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 4 | const struct sockaddr *dest_addr, socklen_t addrlen) 5 | { 6 | bb_simple_perror_msg_and_die("sendto called"); 7 | return -1; 8 | } 9 | 10 | char *mktemp(char *template) 11 | { 12 | bb_simple_perror_msg_and_die("mktemp called"); 13 | return NULL; 14 | } 15 | 16 | int mkstemp(char *template) 17 | { 18 | bb_simple_perror_msg_and_die("mkstemp called"); 19 | return -1; 20 | } 21 | 22 | int _ZNSt9exceptionD2Ev_XXXX() 23 | { 24 | bb_simple_perror_msg_and_die("__ZNSt9exceptionD2Ev called"); 25 | return -1; 26 | } 27 | 28 | //void xregcomp(regex_t *preg, const char *regex, int cflags) 29 | //{ 30 | //bb_simple_perror_msg_and_die("xregcomp called"); 31 | //} 32 | 33 | const char *applet_name = "BusyBoxAwk"; 34 | 35 | // from busybox/applets/individual.c 36 | void bb_show_usage(void) 37 | { 38 | fputs("(BusyBox AWK Usage)\n",stdout); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | int fixed_getopt32(const char* argv[], const char* options, 43 | /* output*/ char* opt_F, 44 | /* output*/ llist_t* list_v, 45 | /* output*/ llist_t* list_f) 46 | { 47 | if (strcmp(options,"F:v:f:W:")!=0) { 48 | bb_simple_perror_msg_and_die("internal error in fixed_getopt32"); 49 | 50 | } 51 | 52 | int argc = 1; 53 | while (argv[argc]) { 54 | node_js_debug("==== getopt32: argv[%d] = '%s'\n", argc, argv[argc]); 55 | argc++; 56 | } 57 | 58 | int c; 59 | int flags=0; 60 | 61 | while ( (c=getopt(argc,argv,options)) != -1 ) { 62 | node_js_debug("==== getopt32: getopt returned '%c'\n", c); 63 | switch(c) 64 | { 65 | case 'F': 66 | flags ^= 1; 67 | opt_F = optarg; 68 | node_js_debug("==== getopt32: setting -F = '%s'\n", opt_F); 69 | break; 70 | 71 | case 'v': 72 | flags ^= 2; 73 | node_js_debug("==== getopt32: adding -V = '%s'\n", optarg); 74 | llist_add_to_end(list_v,optarg); 75 | break; 76 | 77 | case 'f': 78 | flags ^= 4; 79 | node_js_debug("==== getopt32: adding -f = '%s'\n", optarg); 80 | llist_add_to_end(list_f,optarg); 81 | break; 82 | 83 | case 'W': 84 | flags ^= 8; 85 | node_js_debug("==== getopt32: setting -W\n"); 86 | break; 87 | 88 | default: 89 | bb_simple_perror_msg_and_die("invalid command-line argument"); 90 | } 91 | } 92 | 93 | return flags; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /busybox/include/libbb.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBBB_TINY_H__ 2 | #define __LIBBB_TINY_H__ 3 | 4 | //#define NODE_JS_DEBUG 5 | 6 | #ifdef NODE_JS_DEBUG 7 | #define node_js_debug(...) (fprintf(stderr, __VA_ARGS__)) 8 | #else 9 | #define node_js_debug 10 | #endif 11 | 12 | 13 | 14 | #define DISABLE_FOR_WEBACK 1 15 | 16 | typedef signed char smallint; 17 | typedef unsigned char smalluint; 18 | 19 | #define ALIGN1 20 | #define ALIGN2 21 | #define ALWAYS_INLINE 22 | #define NORETURN __attribute__ ((noreturn)) 23 | #define FAST_FUNC 24 | #define ENABLE_DESKTOP 0 25 | #define NOINLINE 26 | #define TRUE 1 27 | #define FALSE 0 28 | #define ENABLE_LOCALE_SUPPORT 0 29 | #define ENABLE_FEATURE_AWK_LIBM 0 30 | #define ENABLE_FEATURE_ALLOW_EXEC 0 31 | #define MAIN_EXTERNALLY_VISIBLE 32 | #define RETURNS_MALLOC 33 | #define ENABLE_DEBUG 0 34 | #define ENABLE_FEATURE_PREFER_APPLETS 0 35 | #define ENABLE_HUSH 0 36 | #define CONFIG_FEATURE_COPYBUF_KB 2 37 | 38 | #define OFF_FMT "l" 39 | #define ENABLE_FEATURE_CLEAN_UP 1 40 | 41 | #define PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 42 | #define POP_SAVED_FUNCTION_VISIBILITY 43 | 44 | #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) 45 | 46 | struct globals *const ptr_to_globals; 47 | 48 | #define SET_PTR_TO_GLOBALS(x) do { \ 49 | (*(struct globals**)&ptr_to_globals) = (void*)(x); \ 50 | } while (0) 51 | 52 | 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | 74 | 75 | #include 76 | 77 | void *malloc_or_warn(size_t size) FAST_FUNC RETURNS_MALLOC; 78 | void *xmalloc(size_t size) FAST_FUNC RETURNS_MALLOC; 79 | void *xzalloc(size_t size) FAST_FUNC RETURNS_MALLOC; 80 | void *xrealloc(void *old, size_t size) FAST_FUNC; 81 | 82 | extern char bb_process_escape_sequence(const char **ptr) FAST_FUNC; 83 | 84 | //Import from: libbb.c 85 | extern void bb_show_usage(void) NORETURN FAST_FUNC; 86 | extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; 87 | extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; 88 | extern void bb_perror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; 89 | extern void bb_simple_perror_msg(const char *s) FAST_FUNC; 90 | extern void bb_perror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; 91 | extern void bb_simple_perror_msg_and_die(const char *s) NORETURN FAST_FUNC; 92 | extern void bb_herror_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; 93 | extern void bb_herror_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))) FAST_FUNC; 94 | extern void bb_perror_nomsg_and_die(void) NORETURN FAST_FUNC; 95 | extern void bb_perror_nomsg(void) FAST_FUNC; 96 | extern void bb_info_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; 97 | extern void bb_verror_msg(const char *s, va_list p, const char *strerr) FAST_FUNC; 98 | 99 | 100 | //Import from: skip_whitespace.c 101 | char* FAST_FUNC skip_whitespace(const char *s); 102 | 103 | //Import from: wfopen.c 104 | FILE* FAST_FUNC fopen_for_read(const char *path); 105 | 106 | //Import from: wfopen_input.c 107 | FILE* FAST_FUNC xfopen_stdin(const char *filename); 108 | 109 | //import from: xfuncs.c 110 | char* FAST_FUNC itoa(int n); 111 | 112 | /* Returns a pointer past the formatted number, does NOT null-terminate */ 113 | char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) FAST_FUNC; 114 | char *itoa_to_buf(int n, char *buf, unsigned buflen) FAST_FUNC; 115 | 116 | void die_if_ferror(FILE *file, const char *msg) FAST_FUNC; 117 | void die_if_ferror_stdout(void) FAST_FUNC; 118 | int fflush_all(void) FAST_FUNC; 119 | void fflush_stdout_and_exit(int retval) NORETURN FAST_FUNC; 120 | int fclose_if_not_stdin(FILE *file) FAST_FUNC; 121 | FILE* xfopen(const char *filename, const char *mode) FAST_FUNC; 122 | FILE* fopen_or_warn(const char *filename, const char *mode) FAST_FUNC; 123 | FILE* xfopen_stdin(const char *filename) FAST_FUNC; 124 | FILE* fopen_or_warn_stdin(const char *filename) FAST_FUNC; 125 | FILE* fopen_for_read(const char *path) FAST_FUNC; 126 | FILE* xfopen_for_read(const char *path) FAST_FUNC; 127 | FILE* fopen_for_write(const char *path) FAST_FUNC; 128 | FILE* xfopen_for_write(const char *path) FAST_FUNC; 129 | FILE* xfdopen_for_read(int fd) FAST_FUNC; 130 | FILE* xfdopen_for_write(int fd) FAST_FUNC; 131 | 132 | //Import from:? 133 | int fflush_all(void) FAST_FUNC; 134 | 135 | //Import from: xfuncs_printf.c 136 | char* FAST_FUNC xasprintf(const char *format, ...); 137 | 138 | extern void xfunc_die(void) NORETURN FAST_FUNC; 139 | 140 | extern const char bb_msg_standard_input[] ALIGN1; 141 | extern const char bb_msg_standard_output[] ALIGN1; 142 | extern const char bb_msg_memory_exhausted[] ALIGN1; 143 | 144 | #define LONE_DASH(s) ((s)[0] == '-' && !(s)[1]) 145 | #define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1]) 146 | #define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1]) 147 | #define NOT_LONE_CHAR(s,c) ((s)[0] != (c) || (s)[1]) 148 | #define DOT_OR_DOTDOT(s) ((s)[0] == '.' && (!(s)[1] || ((s)[1] == '.' && !(s)[2]))) 149 | 150 | enum { 151 | LOGMODE_NONE = 0, 152 | LOGMODE_STDIO = (1 << 0), 153 | //LOGMODE_SYSLOG = (1 << 1) * ENABLE_FEATURE_SYSLOG, 154 | //LOGMODE_BOTH = LOGMODE_SYSLOG + LOGMODE_STDIO, 155 | }; 156 | 157 | extern const char *applet_name; 158 | 159 | extern ssize_t full_write(int fd, const void *buf, size_t count) FAST_FUNC; 160 | 161 | char *xstrdup(const char *s) FAST_FUNC RETURNS_MALLOC; 162 | char *xstrndup(const char *s, int n) FAST_FUNC RETURNS_MALLOC; 163 | void overlapping_strcpy(char *dst, const char *src) FAST_FUNC; 164 | char *safe_strncpy(char *dst, const char *src, size_t size) FAST_FUNC; 165 | 166 | extern ssize_t safe_read(int fd, void *buf, size_t count) FAST_FUNC; 167 | extern ssize_t safe_write(int fd, const void *buf, size_t count) FAST_FUNC; 168 | 169 | extern off_t bb_copyfd_eof(int fd1, int fd2) FAST_FUNC; 170 | extern off_t bb_copyfd_size(int fd1, int fd2, off_t size) FAST_FUNC; 171 | extern void bb_copyfd_exact_size(int fd1, int fd2, off_t size) FAST_FUNC; 172 | 173 | #define bb_msg_read_error "read error" 174 | #define bb_msg_write_error "write error" 175 | 176 | /* NB: (bb_hexdigits_upcase[i] | 0x20) -> lowercase hex digit */ 177 | extern const char bb_hexdigits_upcase[]; 178 | 179 | #define awk_main main 180 | 181 | /* Last element is marked by mult == 0 */ 182 | struct suffix_mult { 183 | char suffix[4]; 184 | unsigned mult; 185 | }; 186 | 187 | /* Having next pointer as a first member allows easy creation 188 | * of "llist-compatible" structs, and using llist_FOO functions 189 | * on them. 190 | */ 191 | typedef struct llist_t { 192 | struct llist_t *link; 193 | char *data; 194 | } llist_t; 195 | void llist_add_to(llist_t **old_head, void *data) FAST_FUNC; 196 | void llist_add_to_end(llist_t **list_head, void *data) FAST_FUNC; 197 | void *llist_pop(llist_t **elm) FAST_FUNC; 198 | void llist_unlink(llist_t **head, llist_t *elm) FAST_FUNC; 199 | void llist_free(llist_t *elm, void (*freeit)(void *data)) FAST_FUNC; 200 | llist_t *llist_rev(llist_t *list) FAST_FUNC; 201 | llist_t *llist_find_str(llist_t *first, const char *str) FAST_FUNC; 202 | 203 | int xatoi_positive(const char *numstr) FAST_FUNC; 204 | 205 | extern const char *opt_complementary; 206 | extern uint32_t getopt32(char **argv, const char *applet_opts, ...) FAST_FUNC; 207 | 208 | extern int vasprintf(char **string_ptr, const char *format, va_list p) FAST_FUNC; 209 | 210 | int fixed_getopt32(const char* argv[], const char* options, 211 | /* output*/ char* opt_F, 212 | /* output*/ llist_t* list_v, 213 | /* output*/ llist_t* list_f); 214 | 215 | #endif 216 | -------------------------------------------------------------------------------- /busybox/include/xregex.h: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Busybox xregcomp utility routine. This isn't in libbb.h because the 4 | * C library we're linking against may not support regex.h. 5 | * 6 | * Based in part on code from sash, Copyright (c) 1999 by David I. Bell 7 | * Permission has been granted to redistribute this code under GPL. 8 | * 9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 | */ 11 | #ifndef BB_REGEX_H 12 | #define BB_REGEX_H 1 13 | 14 | #include 15 | 16 | PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN 17 | 18 | char* regcomp_or_errmsg(regex_t *preg, const char *regex, int cflags) FAST_FUNC; 19 | void xregcomp(regex_t *preg, const char *regex, int cflags) FAST_FUNC; 20 | 21 | POP_SAVED_FUNCTION_VISIBILITY 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /busybox/libbb/copyfd.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2005 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | /* Used by NOFORK applets (e.g. cat) - must not use xmalloc. 13 | * size < 0 means "ignore write errors", used by tar --to-command 14 | * size = 0 means "copy till EOF" 15 | */ 16 | static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) 17 | { 18 | int status = -1; 19 | off_t total = 0; 20 | bool continue_on_write_error = 0; 21 | #if CONFIG_FEATURE_COPYBUF_KB <= 4 22 | char buffer[CONFIG_FEATURE_COPYBUF_KB * 1024]; 23 | enum { buffer_size = sizeof(buffer) }; 24 | #else 25 | char *buffer; 26 | int buffer_size; 27 | #endif 28 | 29 | if (size < 0) { 30 | size = -size; 31 | continue_on_write_error = 1; 32 | } 33 | 34 | #if CONFIG_FEATURE_COPYBUF_KB > 4 35 | if (size > 0 && size <= 4 * 1024) 36 | goto use_small_buf; 37 | /* We want page-aligned buffer, just in case kernel is clever 38 | * and can do page-aligned io more efficiently */ 39 | buffer = mmap(NULL, CONFIG_FEATURE_COPYBUF_KB * 1024, 40 | PROT_READ | PROT_WRITE, 41 | MAP_PRIVATE | MAP_ANON, 42 | /* ignored: */ -1, 0); 43 | buffer_size = CONFIG_FEATURE_COPYBUF_KB * 1024; 44 | if (buffer == MAP_FAILED) { 45 | use_small_buf: 46 | buffer = alloca(4 * 1024); 47 | buffer_size = 4 * 1024; 48 | } 49 | #endif 50 | 51 | if (src_fd < 0) 52 | goto out; 53 | 54 | if (!size) { 55 | size = buffer_size; 56 | status = 1; /* copy until eof */ 57 | } 58 | 59 | while (1) { 60 | ssize_t rd; 61 | 62 | rd = safe_read(src_fd, buffer, size > buffer_size ? buffer_size : size); 63 | 64 | if (!rd) { /* eof - all done */ 65 | status = 0; 66 | break; 67 | } 68 | if (rd < 0) { 69 | bb_perror_msg(bb_msg_read_error); 70 | break; 71 | } 72 | /* dst_fd == -1 is a fake, else... */ 73 | if (dst_fd >= 0) { 74 | ssize_t wr = full_write(dst_fd, buffer, rd); 75 | if (wr < rd) { 76 | if (!continue_on_write_error) { 77 | bb_perror_msg(bb_msg_write_error); 78 | break; 79 | } 80 | dst_fd = -1; 81 | } 82 | } 83 | total += rd; 84 | if (status < 0) { /* if we aren't copying till EOF... */ 85 | size -= rd; 86 | if (!size) { 87 | /* 'size' bytes copied - all done */ 88 | status = 0; 89 | break; 90 | } 91 | } 92 | } 93 | out: 94 | 95 | #if CONFIG_FEATURE_COPYBUF_KB > 4 96 | if (buffer_size != 4 * 1024) 97 | munmap(buffer, buffer_size); 98 | #endif 99 | return status ? -1 : total; 100 | } 101 | 102 | 103 | #if 0 104 | void FAST_FUNC complain_copyfd_and_die(off_t sz) 105 | { 106 | if (sz != -1) 107 | bb_error_msg_and_die("short read"); 108 | /* if sz == -1, bb_copyfd_XX already complained */ 109 | xfunc_die(); 110 | } 111 | #endif 112 | 113 | off_t FAST_FUNC bb_copyfd_size(int fd1, int fd2, off_t size) 114 | { 115 | if (size) { 116 | return bb_full_fd_action(fd1, fd2, size); 117 | } 118 | return 0; 119 | } 120 | 121 | void FAST_FUNC bb_copyfd_exact_size(int fd1, int fd2, off_t size) 122 | { 123 | off_t sz = bb_copyfd_size(fd1, fd2, size); 124 | if (sz == (size >= 0 ? size : -size)) 125 | return; 126 | if (sz != -1) 127 | bb_error_msg_and_die("short read"); 128 | /* if sz == -1, bb_copyfd_XX already complained */ 129 | xfunc_die(); 130 | } 131 | 132 | off_t FAST_FUNC bb_copyfd_eof(int fd1, int fd2) 133 | { 134 | return bb_full_fd_action(fd1, fd2, 0); 135 | } 136 | -------------------------------------------------------------------------------- /busybox/libbb/full_write.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | /* 13 | * Write all of the supplied buffer out to a file. 14 | * This does multiple writes as necessary. 15 | * Returns the amount written, or -1 on an error. 16 | */ 17 | ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len) 18 | { 19 | ssize_t cc; 20 | ssize_t total; 21 | 22 | total = 0; 23 | 24 | while (len) { 25 | cc = safe_write(fd, buf, len); 26 | 27 | if (cc < 0) { 28 | if (total) { 29 | /* we already wrote some! */ 30 | /* user can do another write to know the error code */ 31 | return total; 32 | } 33 | return cc; /* write() returns -1 on failure. */ 34 | } 35 | 36 | total += cc; 37 | buf = ((const char *)buf) + cc; 38 | len -= cc; 39 | } 40 | 41 | return total; 42 | } 43 | -------------------------------------------------------------------------------- /busybox/libbb/getopt32.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * universal getopt32 implementation for busybox 4 | * 5 | * Copyright (C) 2003-2005 Vladimir Oleynik 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG 11 | # include 12 | #endif 13 | #include "libbb.h" 14 | 15 | /* Documentation 16 | 17 | uint32_t 18 | getopt32(char **argv, const char *applet_opts, ...) 19 | 20 | The command line options must be declared in const char 21 | *applet_opts as a string of chars, for example: 22 | 23 | flags = getopt32(argv, "rnug"); 24 | 25 | If one of the given options is found, a flag value is added to 26 | the return value (an unsigned long). 27 | 28 | The flag value is determined by the position of the char in 29 | applet_opts string. For example, in the above case: 30 | 31 | flags = getopt32(argv, "rnug"); 32 | 33 | "r" will add 1 (bit 0) 34 | "n" will add 2 (bit 1) 35 | "u" will add 4 (bit 2) 36 | "g" will add 8 (bit 3) 37 | 38 | and so on. You can also look at the return value as a bit 39 | field and each option sets one bit. 40 | 41 | On exit, global variable optind is set so that if you 42 | will do argc -= optind; argv += optind; then 43 | argc will be equal to number of remaining non-option 44 | arguments, first one would be in argv[0], next in argv[1] and so on 45 | (options and their parameters will be moved into argv[] 46 | positions prior to argv[optind]). 47 | 48 | ":" If one of the options requires an argument, then add a ":" 49 | after the char in applet_opts and provide a pointer to store 50 | the argument. For example: 51 | 52 | char *pointer_to_arg_for_a; 53 | char *pointer_to_arg_for_b; 54 | char *pointer_to_arg_for_c; 55 | char *pointer_to_arg_for_d; 56 | 57 | flags = getopt32(argv, "a:b:c:d:", 58 | &pointer_to_arg_for_a, &pointer_to_arg_for_b, 59 | &pointer_to_arg_for_c, &pointer_to_arg_for_d); 60 | 61 | The type of the pointer (char* or llist_t*) may be controlled 62 | by the "::" special separator that is set in the external string 63 | opt_complementary (see below for more info). 64 | 65 | "::" If option can have an *optional* argument, then add a "::" 66 | after its char in applet_opts and provide a pointer to store 67 | the argument. Note that optional arguments _must_ 68 | immediately follow the option: -oparam, not -o param. 69 | 70 | "+" If the first character in the applet_opts string is a plus, 71 | then option processing will stop as soon as a non-option is 72 | encountered in the argv array. Useful for applets like env 73 | which should not process arguments to subprograms: 74 | env -i ls -d / 75 | Here we want env to process just the '-i', not the '-d'. 76 | 77 | "!" Report bad option, missing required options, 78 | inconsistent options with all-ones return value (instead of abort). 79 | 80 | const char *applet_long_options 81 | 82 | This struct allows you to define long options: 83 | 84 | static const char applet_longopts[] ALIGN1 = 85 | //"name\0" has_arg val 86 | "verbose\0" No_argument "v" 87 | ; 88 | applet_long_options = applet_longopts; 89 | 90 | The last member of struct option (val) typically is set to 91 | matching short option from applet_opts. If there is no matching 92 | char in applet_opts, then: 93 | - return bit have next position after short options 94 | - if has_arg is not "No_argument", use ptr for arg also 95 | - opt_complementary affects it too 96 | 97 | Note: a good applet will make long options configurable via the 98 | config process and not a required feature. The current standard 99 | is to name the config option CONFIG_FEATURE__LONG_OPTIONS. 100 | 101 | const char *opt_complementary 102 | 103 | ":" The colon (":") is used to separate groups of two or more chars 104 | and/or groups of chars and special characters (stating some 105 | conditions to be checked). 106 | 107 | "abc" If groups of two or more chars are specified, the first char 108 | is the main option and the other chars are secondary options. 109 | Their flags will be turned on if the main option is found even 110 | if they are not specifed on the command line. For example: 111 | 112 | opt_complementary = "abc"; 113 | flags = getopt32(argv, "abcd") 114 | 115 | If getopt() finds "-a" on the command line, then 116 | getopt32's return value will be as if "-a -b -c" were 117 | found. 118 | 119 | "ww" Adjacent double options have a counter associated which indicates 120 | the number of occurrences of the option. 121 | For example the ps applet needs: 122 | if w is given once, GNU ps sets the width to 132, 123 | if w is given more than once, it is "unlimited" 124 | 125 | int w_counter = 0; // must be initialized! 126 | opt_complementary = "ww"; 127 | getopt32(argv, "w", &w_counter); 128 | if (w_counter) 129 | width = (w_counter == 1) ? 132 : INT_MAX; 130 | else 131 | get_terminal_width(...&width...); 132 | 133 | w_counter is a pointer to an integer. It has to be passed to 134 | getopt32() after all other option argument sinks. 135 | 136 | For example: accept multiple -v to indicate the level of verbosity 137 | and for each -b optarg, add optarg to my_b. Finally, if b is given, 138 | turn off c and vice versa: 139 | 140 | llist_t *my_b = NULL; 141 | int verbose_level = 0; 142 | opt_complementary = "vv:b::b-c:c-b"; 143 | f = getopt32(argv, "vb:c", &my_b, &verbose_level); 144 | if (f & 2) // -c after -b unsets -b flag 145 | while (my_b) dosomething_with(llist_pop(&my_b)); 146 | if (my_b) // but llist is stored if -b is specified 147 | free_llist(my_b); 148 | if (verbose_level) printf("verbose level is %d\n", verbose_level); 149 | 150 | Special characters: 151 | 152 | "-" A group consisting of just a dash forces all arguments 153 | to be treated as options, even if they have no leading dashes. 154 | Next char in this case can't be a digit (0-9), use ':' or end of line. 155 | Example: 156 | 157 | opt_complementary = "-:w-x:x-w"; // "-w-x:x-w" would also work, 158 | getopt32(argv, "wx"); // but is less readable 159 | 160 | This makes it possible to use options without a dash (./program w x) 161 | as well as with a dash (./program -x). 162 | 163 | NB: getopt32() will leak a small amount of memory if you use 164 | this option! Do not use it if there is a possibility of recursive 165 | getopt32() calls. 166 | 167 | "--" A double dash at the beginning of opt_complementary means the 168 | argv[1] string should always be treated as options, even if it isn't 169 | prefixed with a "-". This is useful for special syntax in applets 170 | such as "ar" and "tar": 171 | tar xvf foo.tar 172 | 173 | NB: getopt32() will leak a small amount of memory if you use 174 | this option! Do not use it if there is a possibility of recursive 175 | getopt32() calls. 176 | 177 | "-N" A dash as the first char in a opt_complementary group followed 178 | by a single digit (0-9) means that at least N non-option 179 | arguments must be present on the command line 180 | 181 | "=N" An equal sign as the first char in a opt_complementary group followed 182 | by a single digit (0-9) means that exactly N non-option 183 | arguments must be present on the command line 184 | 185 | "?N" A "?" as the first char in a opt_complementary group followed 186 | by a single digit (0-9) means that at most N arguments must be present 187 | on the command line. 188 | 189 | "V-" An option with dash before colon or end-of-line results in 190 | bb_show_usage() being called if this option is encountered. 191 | This is typically used to implement "print verbose usage message 192 | and exit" option. 193 | 194 | "a-b" A dash between two options causes the second of the two 195 | to be unset (and ignored) if it is given on the command line. 196 | 197 | [FIXME: what if they are the same? like "x-x"? Is it ever useful?] 198 | 199 | For example: 200 | The du applet has the options "-s" and "-d depth". If 201 | getopt32 finds -s, then -d is unset or if it finds -d 202 | then -s is unset. (Note: busybox implements the GNU 203 | "--max-depth" option as "-d".) To obtain this behavior, you 204 | set opt_complementary = "s-d:d-s". Only one flag value is 205 | added to getopt32's return value depending on the 206 | position of the options on the command line. If one of the 207 | two options requires an argument pointer (":" in applet_opts 208 | as in "d:") optarg is set accordingly. 209 | 210 | char *smax_print_depth; 211 | 212 | opt_complementary = "s-d:d-s:x-x"; 213 | opt = getopt32(argv, "sd:x", &smax_print_depth); 214 | 215 | if (opt & 2) 216 | max_print_depth = atoi(smax_print_depth); 217 | if (opt & 4) 218 | printf("Detected odd -x usage\n"); 219 | 220 | "a--b" A double dash between two options, or between an option and a group 221 | of options, means that they are mutually exclusive. Unlike 222 | the "-" case above, an error will be forced if the options 223 | are used together. 224 | 225 | For example: 226 | The cut applet must have only one type of list specified, so 227 | -b, -c and -f are mutually exclusive and should raise an error 228 | if specified together. In this case you must set 229 | opt_complementary = "b--cf:c--bf:f--bc". If two of the 230 | mutually exclusive options are found, getopt32 will call 231 | bb_show_usage() and die. 232 | 233 | "x--x" Variation of the above, it means that -x option should occur 234 | at most once. 235 | 236 | "a+" A plus after a char in opt_complementary means that the parameter 237 | for this option is a nonnegative integer. It will be processed 238 | with xatoi_positive() - allowed range is 0..INT_MAX. 239 | 240 | int param; // "unsigned param;" will also work 241 | opt_complementary = "p+"; 242 | getopt32(argv, "p:", ¶m); 243 | 244 | "a::" A double colon after a char in opt_complementary means that the 245 | option can occur multiple times. Each occurrence will be saved as 246 | a llist_t element instead of char*. 247 | 248 | For example: 249 | The grep applet can have one or more "-e pattern" arguments. 250 | In this case you should use getopt32() as follows: 251 | 252 | llist_t *patterns = NULL; 253 | 254 | (this pointer must be initializated to NULL if the list is empty 255 | as required by llist_add_to_end(llist_t **old_head, char *new_item).) 256 | 257 | opt_complementary = "e::"; 258 | 259 | getopt32(argv, "e:", &patterns); 260 | $ grep -e user -e root /etc/passwd 261 | root:x:0:0:root:/root:/bin/bash 262 | user:x:500:500::/home/user:/bin/bash 263 | 264 | "a?b" A "?" between an option and a group of options means that 265 | at least one of them is required to occur if the first option 266 | occurs in preceding command line arguments. 267 | 268 | For example from "id" applet: 269 | 270 | // Don't allow -n -r -rn -ug -rug -nug -rnug 271 | opt_complementary = "r?ug:n?ug:u--g:g--u"; 272 | flags = getopt32(argv, "rnug"); 273 | 274 | This example allowed only: 275 | $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng 276 | 277 | "X" A opt_complementary group with just a single letter means 278 | that this option is required. If more than one such group exists, 279 | at least one option is required to occur (not all of them). 280 | For example from "start-stop-daemon" applet: 281 | 282 | // Don't allow -KS -SK, but -S or -K is required 283 | opt_complementary = "K:S:K--S:S--K"; 284 | flags = getopt32(argv, "KS...); 285 | 286 | 287 | Don't forget to use ':'. For example, "?322-22-23X-x-a" 288 | is interpreted as "?3:22:-2:2-2:2-3Xa:2--x" - 289 | max 3 args; count uses of '-2'; min 2 args; if there is 290 | a '-2' option then unset '-3', '-X' and '-a'; if there is 291 | a '-2' and after it a '-x' then error out. 292 | But it's far too obfuscated. Use ':' to separate groups. 293 | */ 294 | 295 | /* Code here assumes that 'unsigned' is at least 32 bits wide */ 296 | 297 | const char *const bb_argv_dash[] = { "-", NULL }; 298 | 299 | const char *opt_complementary; 300 | 301 | enum { 302 | PARAM_STRING, 303 | PARAM_LIST, 304 | PARAM_INT, 305 | }; 306 | 307 | typedef struct { 308 | unsigned char opt_char; 309 | smallint param_type; 310 | unsigned switch_on; 311 | unsigned switch_off; 312 | unsigned incongruously; 313 | unsigned requires; 314 | void **optarg; /* char**, llist_t** or int *. */ 315 | int *counter; 316 | } t_complementary; 317 | 318 | /* You can set applet_long_options for parse called long options */ 319 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG 320 | static const struct option bb_null_long_options[1] = { 321 | { 0, 0, 0, 0 } 322 | }; 323 | const char *applet_long_options; 324 | #endif 325 | 326 | uint32_t option_mask32; 327 | 328 | uint32_t FAST_FUNC 329 | getopt32(char **argv, const char *applet_opts, ...) 330 | { 331 | int argc; 332 | unsigned flags = 0; 333 | unsigned requires = 0; 334 | t_complementary complementary[33]; /* last stays zero-filled */ 335 | char first_char; 336 | int c; 337 | const unsigned char *s; 338 | t_complementary *on_off; 339 | va_list p; 340 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG 341 | const struct option *l_o; 342 | struct option *long_options = (struct option *) &bb_null_long_options; 343 | #endif 344 | unsigned trigger; 345 | char **pargv; 346 | int min_arg = 0; 347 | int max_arg = -1; 348 | 349 | #define SHOW_USAGE_IF_ERROR 1 350 | #define ALL_ARGV_IS_OPTS 2 351 | #define FIRST_ARGV_IS_OPT 4 352 | 353 | int spec_flgs = 0; 354 | 355 | /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ 356 | argc = 1; 357 | while (argv[argc]) { 358 | node_js_debug("==== getopt32: argv[%d] = '%s'\n", argc, argv[argc]); 359 | argc++; 360 | } 361 | 362 | va_start(p, applet_opts); 363 | 364 | c = 0; 365 | on_off = complementary; 366 | memset(on_off, 0, sizeof(complementary)); 367 | 368 | /* skip bbox extension */ 369 | first_char = applet_opts[0]; 370 | if (first_char == '!') 371 | applet_opts++; 372 | 373 | /* skip GNU extension */ 374 | s = (const unsigned char *)applet_opts; 375 | if (*s == '+' || *s == '-') 376 | s++; 377 | while (*s) { 378 | if (c >= 32) 379 | break; 380 | on_off->opt_char = *s; 381 | on_off->switch_on = (1 << c); 382 | if (*++s == ':') { 383 | on_off->optarg = va_arg(p, void **); 384 | while (*++s == ':') 385 | continue; 386 | } 387 | on_off++; 388 | c++; 389 | } 390 | 391 | #if ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG 392 | if (applet_long_options) { 393 | const char *optstr; 394 | unsigned i, count; 395 | 396 | count = 1; 397 | optstr = applet_long_options; 398 | while (optstr[0]) { 399 | optstr += strlen(optstr) + 3; /* skip NUL, has_arg, val */ 400 | count++; 401 | } 402 | /* count == no. of longopts + 1 */ 403 | long_options = alloca(count * sizeof(*long_options)); 404 | memset(long_options, 0, count * sizeof(*long_options)); 405 | i = 0; 406 | optstr = applet_long_options; 407 | while (--count) { 408 | long_options[i].name = optstr; 409 | optstr += strlen(optstr) + 1; 410 | long_options[i].has_arg = (unsigned char)(*optstr++); 411 | /* long_options[i].flag = NULL; */ 412 | long_options[i].val = (unsigned char)(*optstr++); 413 | i++; 414 | } 415 | for (l_o = long_options; l_o->name; l_o++) { 416 | if (l_o->flag) 417 | continue; 418 | for (on_off = complementary; on_off->opt_char; on_off++) 419 | if (on_off->opt_char == l_o->val) 420 | goto next_long; 421 | if (c >= 32) 422 | break; 423 | on_off->opt_char = l_o->val; 424 | on_off->switch_on = (1 << c); 425 | if (l_o->has_arg != no_argument) 426 | on_off->optarg = va_arg(p, void **); 427 | c++; 428 | next_long: ; 429 | } 430 | /* Make it unnecessary to clear applet_long_options 431 | * by hand after each call to getopt32 432 | */ 433 | applet_long_options = NULL; 434 | } 435 | #endif /* ENABLE_LONG_OPTS || ENABLE_FEATURE_GETOPT_LONG */ 436 | for (s = (const unsigned char *)opt_complementary; s && *s; s++) { 437 | t_complementary *pair; 438 | unsigned *pair_switch; 439 | 440 | if (*s == ':') 441 | continue; 442 | c = s[1]; 443 | if (*s == '?') { 444 | if (c < '0' || c > '9') { 445 | spec_flgs |= SHOW_USAGE_IF_ERROR; 446 | } else { 447 | max_arg = c - '0'; 448 | s++; 449 | } 450 | continue; 451 | } 452 | if (*s == '-') { 453 | if (c < '0' || c > '9') { 454 | if (c == '-') { 455 | spec_flgs |= FIRST_ARGV_IS_OPT; 456 | s++; 457 | } else 458 | spec_flgs |= ALL_ARGV_IS_OPTS; 459 | } else { 460 | min_arg = c - '0'; 461 | s++; 462 | } 463 | continue; 464 | } 465 | if (*s == '=') { 466 | min_arg = max_arg = c - '0'; 467 | s++; 468 | continue; 469 | } 470 | for (on_off = complementary; on_off->opt_char; on_off++) 471 | if (on_off->opt_char == *s) 472 | goto found_opt; 473 | /* Without this, diagnostic of such bugs is not easy */ 474 | bb_error_msg_and_die("NO OPT %c!", *s); 475 | found_opt: 476 | if (c == ':' && s[2] == ':') { 477 | on_off->param_type = PARAM_LIST; 478 | continue; 479 | } 480 | if (c == '+' && (s[2] == ':' || s[2] == '\0')) { 481 | on_off->param_type = PARAM_INT; 482 | s++; 483 | continue; 484 | } 485 | if (c == ':' || c == '\0') { 486 | requires |= on_off->switch_on; 487 | continue; 488 | } 489 | if (c == '-' && (s[2] == ':' || s[2] == '\0')) { 490 | flags |= on_off->switch_on; 491 | on_off->incongruously |= on_off->switch_on; 492 | s++; 493 | continue; 494 | } 495 | if (c == *s) { 496 | on_off->counter = va_arg(p, int *); 497 | s++; 498 | } 499 | pair = on_off; 500 | pair_switch = &pair->switch_on; 501 | for (s++; *s && *s != ':'; s++) { 502 | if (*s == '?') { 503 | pair_switch = &pair->requires; 504 | } else if (*s == '-') { 505 | if (pair_switch == &pair->switch_off) 506 | pair_switch = &pair->incongruously; 507 | else 508 | pair_switch = &pair->switch_off; 509 | } else { 510 | for (on_off = complementary; on_off->opt_char; on_off++) 511 | if (on_off->opt_char == *s) { 512 | *pair_switch |= on_off->switch_on; 513 | break; 514 | } 515 | } 516 | } 517 | s--; 518 | } 519 | opt_complementary = NULL; 520 | va_end(p); 521 | 522 | if (spec_flgs & (FIRST_ARGV_IS_OPT | ALL_ARGV_IS_OPTS)) { 523 | pargv = argv + 1; 524 | while (*pargv) { 525 | if (pargv[0][0] != '-' && pargv[0][0] != '\0') { 526 | /* Can't use alloca: opts with params will 527 | * return pointers to stack! 528 | * NB: we leak these allocations... */ 529 | char *pp = xmalloc(strlen(*pargv) + 2); 530 | *pp = '-'; 531 | strcpy(pp + 1, *pargv); 532 | *pargv = pp; 533 | } 534 | if (!(spec_flgs & ALL_ARGV_IS_OPTS)) 535 | break; 536 | pargv++; 537 | } 538 | } 539 | 540 | /* In case getopt32 was already called: 541 | * reset the libc getopt() function, which keeps internal state. 542 | * run_nofork_applet() does this, but we might end up here 543 | * also via gunzip_main() -> gzip_main(). Play safe. 544 | */ 545 | #ifdef __GLIBC__ 546 | optind = 0; 547 | #else /* BSD style */ 548 | optind = 1; 549 | /* optreset = 1; */ 550 | #endif 551 | optarg = NULL; opterr = 0; optopt = 0; //- do we need this?? */ 552 | 553 | node_js_debug("==== getopt32: applet_opts = %s\n", applet_opts); 554 | for (int i=0;iopt_char != c; on_off++) { 573 | /* c can be NUL if long opt has non-NULL ->flag, 574 | * but we construct long opts so that flag 575 | * is always NULL (see above) */ 576 | if (on_off->opt_char == '\0' /* && c != '\0' */) { 577 | /* c is probably '?' - "bad option" */ 578 | goto error; 579 | } 580 | } 581 | if (flags & on_off->incongruously) 582 | goto error; 583 | trigger = on_off->switch_on & on_off->switch_off; 584 | flags &= ~(on_off->switch_off ^ trigger); 585 | flags |= on_off->switch_on ^ trigger; 586 | flags ^= trigger; 587 | if (on_off->counter) 588 | (*(on_off->counter))++; 589 | if (optarg) { 590 | if (on_off->param_type == PARAM_LIST) { 591 | llist_add_to_end((llist_t **)(on_off->optarg), optarg); 592 | } else if (on_off->param_type == PARAM_INT) { 593 | //TODO: xatoi_positive indirectly pulls in printf machinery 594 | *(unsigned*)(on_off->optarg) = xatoi_positive(optarg); 595 | } else if (on_off->optarg) { 596 | *(char **)(on_off->optarg) = optarg; 597 | } 598 | } 599 | } 600 | 601 | /* check depending requires for given options */ 602 | for (on_off = complementary; on_off->opt_char; on_off++) { 603 | if (on_off->requires 604 | && (flags & on_off->switch_on) 605 | && (flags & on_off->requires) == 0 606 | ) { 607 | goto error; 608 | } 609 | } 610 | if (requires && (flags & requires) == 0) 611 | goto error; 612 | argc -= optind; 613 | if (argc < min_arg || (max_arg >= 0 && argc > max_arg)) 614 | goto error; 615 | 616 | option_mask32 = flags; 617 | return flags; 618 | 619 | error: 620 | if (first_char != '!') 621 | bb_show_usage(); 622 | return (int32_t)-1; 623 | } 624 | -------------------------------------------------------------------------------- /busybox/libbb/llist.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * linked list helper functions. 4 | * 5 | * Copyright (C) 2003 Glenn McGrath 6 | * Copyright (C) 2005 Vladimir Oleynik 7 | * Copyright (C) 2005 Bernhard Reutner-Fischer 8 | * Copyright (C) 2006 Rob Landley 9 | * 10 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 | */ 12 | 13 | #include "libbb.h" 14 | 15 | /* Add data to the start of the linked list. */ 16 | void FAST_FUNC llist_add_to(llist_t **old_head, void *data) 17 | { 18 | llist_t *new_head = xmalloc(sizeof(llist_t)); 19 | 20 | new_head->data = data; 21 | new_head->link = *old_head; 22 | *old_head = new_head; 23 | } 24 | 25 | /* Add data to the end of the linked list. */ 26 | void FAST_FUNC llist_add_to_end(llist_t **list_head, void *data) 27 | { 28 | while (*list_head) 29 | list_head = &(*list_head)->link; 30 | *list_head = xzalloc(sizeof(llist_t)); 31 | (*list_head)->data = data; 32 | /*(*list_head)->link = NULL;*/ 33 | } 34 | 35 | /* Remove first element from the list and return it */ 36 | void* FAST_FUNC llist_pop(llist_t **head) 37 | { 38 | void *data = NULL; 39 | llist_t *temp = *head; 40 | 41 | if (temp) { 42 | data = temp->data; 43 | *head = temp->link; 44 | free(temp); 45 | } 46 | return data; 47 | } 48 | 49 | /* Unlink arbitrary given element from the list */ 50 | void FAST_FUNC llist_unlink(llist_t **head, llist_t *elm) 51 | { 52 | if (!elm) 53 | return; 54 | while (*head) { 55 | if (*head == elm) { 56 | *head = (*head)->link; 57 | break; 58 | } 59 | head = &(*head)->link; 60 | } 61 | } 62 | 63 | /* Recursively free all elements in the linked list. If freeit != NULL 64 | * call it on each datum in the list */ 65 | void FAST_FUNC llist_free(llist_t *elm, void (*freeit)(void *data)) 66 | { 67 | while (elm) { 68 | void *data = llist_pop(&elm); 69 | 70 | if (freeit) 71 | freeit(data); 72 | } 73 | } 74 | 75 | /* Reverse list order. */ 76 | llist_t* FAST_FUNC llist_rev(llist_t *list) 77 | { 78 | llist_t *rev = NULL; 79 | 80 | while (list) { 81 | llist_t *next = list->link; 82 | 83 | list->link = rev; 84 | rev = list; 85 | list = next; 86 | } 87 | return rev; 88 | } 89 | 90 | llist_t* FAST_FUNC llist_find_str(llist_t *list, const char *str) 91 | { 92 | while (list) { 93 | if (strcmp(list->data, str) == 0) 94 | break; 95 | list = list->link; 96 | } 97 | return list; 98 | } 99 | -------------------------------------------------------------------------------- /busybox/libbb/messages.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Copyright (C) 1999-2004 by Erik Andersen 4 | * 5 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 | */ 7 | 8 | #include "libbb.h" 9 | 10 | /* allow default system PATH to be extended via CFLAGS */ 11 | #ifndef BB_ADDITIONAL_PATH 12 | #define BB_ADDITIONAL_PATH "" 13 | #endif 14 | 15 | /* allow version to be extended, via CFLAGS */ 16 | #ifndef BB_EXTRA_VERSION 17 | #define BB_EXTRA_VERSION BB_BT 18 | #endif 19 | 20 | #define BANNER "BusyBox v" BB_VER " (" BB_EXTRA_VERSION ")" 21 | 22 | //const char bb_banner[] ALIGN1 = BANNER; 23 | 24 | 25 | const char bb_msg_memory_exhausted[] ALIGN1 = "out of memory"; 26 | const char bb_msg_invalid_date[] ALIGN1 = "invalid date '%s'"; 27 | const char bb_msg_unknown[] ALIGN1 = "(unknown)"; 28 | const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"; 29 | const char bb_msg_perm_denied_are_you_root[] ALIGN1 = "permission denied (are you root?)"; 30 | const char bb_msg_you_must_be_root[] ALIGN1 = "you must be root"; 31 | const char bb_msg_requires_arg[] ALIGN1 = "%s requires an argument"; 32 | const char bb_msg_invalid_arg[] ALIGN1 = "invalid argument '%s' to '%s'"; 33 | const char bb_msg_standard_input[] ALIGN1 = "standard input"; 34 | const char bb_msg_standard_output[] ALIGN1 = "standard output"; 35 | 36 | const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF"; 37 | 38 | //const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH; 39 | //const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL; 40 | 41 | /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin, 42 | * but I want to save a few bytes here. Check libbb.h before changing! */ 43 | const char bb_PATH_root_path[] ALIGN1 = 44 | "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH; 45 | 46 | 47 | const int const_int_1 = 1; 48 | /* explicitly = 0, otherwise gcc may make it a common variable 49 | * and it will end up in bss */ 50 | const int const_int_0 = 0; 51 | 52 | #if ENABLE_FEATURE_WTMP 53 | /* This is usually something like "/var/adm/wtmp" or "/var/log/wtmp" */ 54 | const char bb_path_wtmp_file[] ALIGN1 = 55 | # if defined _PATH_WTMP 56 | _PATH_WTMP; 57 | # elif defined WTMP_FILE 58 | WTMP_FILE; 59 | # else 60 | # error unknown path to wtmp file 61 | # endif 62 | #endif 63 | 64 | /* We use it for "global" data via *(struct global*)&bb_common_bufsiz1. 65 | * Since gcc insists on aligning struct global's members, it would be a pity 66 | * (and an alignment fault on some CPUs) to mess it up. */ 67 | //char bb_common_bufsiz1[COMMON_BUFSIZE] ALIGNED(sizeof(long long)); 68 | -------------------------------------------------------------------------------- /busybox/libbb/perror_msg.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | #include "libbb.h" 10 | 11 | void FAST_FUNC bb_perror_msg(const char *s, ...) 12 | { 13 | va_list p; 14 | 15 | va_start(p, s); 16 | /* Guard against ": Success" */ 17 | bb_verror_msg(s, p, errno ? strerror(errno) : NULL); 18 | va_end(p); 19 | } 20 | 21 | void FAST_FUNC bb_perror_msg_and_die(const char *s, ...) 22 | { 23 | va_list p; 24 | 25 | va_start(p, s); 26 | /* Guard against ": Success" */ 27 | bb_verror_msg(s, p, errno ? strerror(errno) : NULL); 28 | va_end(p); 29 | xfunc_die(); 30 | } 31 | 32 | void FAST_FUNC bb_simple_perror_msg(const char *s) 33 | { 34 | bb_perror_msg("%s", s); 35 | } 36 | 37 | void FAST_FUNC bb_simple_perror_msg_and_die(const char *s) 38 | { 39 | bb_perror_msg_and_die("%s", s); 40 | } 41 | -------------------------------------------------------------------------------- /busybox/libbb/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Replacements for common but usually nonstandard functions that aren't 3 | * supplied by all platforms. 4 | * 5 | * Copyright (C) 2009 by Dan Fandrich , et. al. 6 | * 7 | * Licensed under GPLv2, see file LICENSE in this source tree. 8 | */ 9 | #include "libbb.h" 10 | 11 | #ifndef HAVE_STRCHRNUL 12 | char* FAST_FUNC strchrnul(const char *s, int c) 13 | { 14 | while (*s != '\0' && *s != c) 15 | s++; 16 | return (char*)s; 17 | } 18 | #endif 19 | 20 | #ifndef HAVE_VASPRINTF 21 | int FAST_FUNC vasprintf(char **string_ptr, const char *format, va_list p) 22 | { 23 | int r; 24 | va_list p2; 25 | char buf[128]; 26 | 27 | va_copy(p2, p); 28 | r = vsnprintf(buf, 128, format, p); 29 | va_end(p); 30 | 31 | if (r < 128) { 32 | va_end(p2); 33 | *string_ptr = xstrdup(buf); 34 | return r; 35 | } 36 | 37 | *string_ptr = xmalloc(r+1); 38 | r = vsnprintf(*string_ptr, r+1, format, p2); 39 | va_end(p2); 40 | 41 | return r; 42 | } 43 | #endif 44 | 45 | #ifndef HAVE_DPRINTF 46 | /* dprintf is now part of POSIX.1, but was only added in 2008 */ 47 | int dprintf(int fd, const char *format, ...) 48 | { 49 | va_list p; 50 | int r; 51 | char *string_ptr; 52 | 53 | va_start(p, format); 54 | r = vasprintf(&string_ptr, format, p); 55 | va_end(p); 56 | if (r >= 0) { 57 | r = full_write(fd, string_ptr, r); 58 | free(string_ptr); 59 | } 60 | return r; 61 | } 62 | #endif 63 | 64 | #ifndef HAVE_MEMRCHR 65 | /* Copyright (C) 2005 Free Software Foundation, Inc. 66 | * memrchr() is a GNU function that might not be available everywhere. 67 | * It's basically the inverse of memchr() - search backwards in a 68 | * memory block for a particular character. 69 | */ 70 | void* FAST_FUNC memrchr(const void *s, int c, size_t n) 71 | { 72 | const char *start = s, *end = s; 73 | 74 | end += n - 1; 75 | 76 | while (end >= start) { 77 | if (*end == (char)c) 78 | return (void *) end; 79 | end--; 80 | } 81 | 82 | return NULL; 83 | } 84 | #endif 85 | 86 | #ifndef HAVE_MKDTEMP 87 | /* This is now actually part of POSIX.1, but was only added in 2008 */ 88 | char* FAST_FUNC mkdtemp(char *template) 89 | { 90 | if (mktemp(template) == NULL || mkdir(template, 0700) != 0) 91 | return NULL; 92 | return template; 93 | } 94 | #endif 95 | 96 | #ifndef HAVE_STRCASESTR 97 | /* Copyright (c) 1999, 2000 The ht://Dig Group */ 98 | char* FAST_FUNC strcasestr(const char *s, const char *pattern) 99 | { 100 | int length = strlen(pattern); 101 | 102 | while (*s) { 103 | if (strncasecmp(s, pattern, length) == 0) 104 | return (char *)s; 105 | s++; 106 | } 107 | return 0; 108 | } 109 | #endif 110 | 111 | #ifndef HAVE_STRSEP 112 | /* Copyright (C) 2004 Free Software Foundation, Inc. */ 113 | char* FAST_FUNC strsep(char **stringp, const char *delim) 114 | { 115 | char *start = *stringp; 116 | char *ptr; 117 | 118 | if (!start) 119 | return NULL; 120 | 121 | if (!*delim) 122 | ptr = start + strlen(start); 123 | else { 124 | ptr = strpbrk(start, delim); 125 | if (!ptr) { 126 | *stringp = NULL; 127 | return start; 128 | } 129 | } 130 | 131 | *ptr = '\0'; 132 | *stringp = ptr + 1; 133 | 134 | return start; 135 | } 136 | #endif 137 | 138 | #ifndef HAVE_STPCPY 139 | char* FAST_FUNC stpcpy(char *p, const char *to_add) 140 | { 141 | while ((*p = *to_add) != '\0') { 142 | p++; 143 | to_add++; 144 | } 145 | return p; 146 | } 147 | #endif 148 | 149 | #ifndef HAVE_GETLINE 150 | ssize_t FAST_FUNC getline(char **lineptr, size_t *n, FILE *stream) 151 | { 152 | int ch; 153 | char *line = *lineptr; 154 | size_t alloced = *n; 155 | size_t len = 0; 156 | 157 | do { 158 | ch = fgetc(stream); 159 | if (ch == EOF) 160 | break; 161 | if (len + 1 >= alloced) { 162 | alloced += alloced/4 + 64; 163 | line = xrealloc(line, alloced); 164 | } 165 | line[len++] = ch; 166 | } while (ch != '\n'); 167 | 168 | if (len == 0) 169 | return -1; 170 | 171 | line[len] = '\0'; 172 | *lineptr = line; 173 | *n = alloced; 174 | return len; 175 | } 176 | #endif 177 | -------------------------------------------------------------------------------- /busybox/libbb/process_escape_sequence.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) Manuel Novoa III 6 | * and Vladimir Oleynik 7 | * 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 | */ 10 | 11 | #include "libbb.h" 12 | 13 | #define WANT_HEX_ESCAPES 1 14 | 15 | /* Usual "this only works for ascii compatible encodings" disclaimer. */ 16 | #undef _tolower 17 | #define _tolower(X) ((X)|((char) 0x20)) 18 | 19 | char FAST_FUNC bb_process_escape_sequence(const char **ptr) 20 | { 21 | const char *q; 22 | unsigned num_digits; 23 | unsigned n; 24 | unsigned base; 25 | 26 | num_digits = n = 0; 27 | base = 8; 28 | q = *ptr; 29 | 30 | if (WANT_HEX_ESCAPES && *q == 'x') { 31 | ++q; 32 | base = 16; 33 | ++num_digits; 34 | } 35 | 36 | /* bash requires leading 0 in octal escapes: 37 | * \02 works, \2 does not (prints \ and 2). 38 | * We treat \2 as a valid octal escape sequence. */ 39 | do { 40 | unsigned r; 41 | #if !WANT_HEX_ESCAPES 42 | unsigned d = (unsigned char)(*q) - '0'; 43 | #else 44 | unsigned d = (unsigned char)_tolower(*q) - '0'; 45 | if (d >= 10) 46 | d += ('0' - 'a' + 10); 47 | #endif 48 | if (d >= base) { 49 | if (WANT_HEX_ESCAPES && base == 16) { 50 | --num_digits; 51 | if (num_digits == 0) { 52 | /* \x: return '\', 53 | * leave ptr pointing to x */ 54 | return '\\'; 55 | } 56 | } 57 | break; 58 | } 59 | 60 | r = n * base + d; 61 | if (r > UCHAR_MAX) { 62 | break; 63 | } 64 | 65 | n = r; 66 | ++q; 67 | } while (++num_digits < 3); 68 | 69 | if (num_digits == 0) { 70 | /* Not octal or hex escape sequence. 71 | * Is it one-letter one? */ 72 | 73 | /* bash builtin "echo -e '\ec'" interprets \e as ESC, 74 | * but coreutils "/bin/echo -e '\ec'" does not. 75 | * Manpages tend to support coreutils way. 76 | * Update: coreutils added support for \e on 28 Oct 2009. */ 77 | static const char charmap[] ALIGN1 = { 78 | 'a', 'b', 'e', 'f', 'n', 'r', 't', 'v', '\\', '\0', 79 | '\a', '\b', 27, '\f', '\n', '\r', '\t', '\v', '\\', '\\', 80 | }; 81 | const char *p = charmap; 82 | do { 83 | if (*p == *q) { 84 | q++; 85 | break; 86 | } 87 | } while (*++p != '\0'); 88 | /* p points to found escape char or NUL, 89 | * advance it and find what it translates to. 90 | * Note that \NUL and unrecognized sequence \z return '\' 91 | * and leave ptr pointing to NUL or z. */ 92 | n = p[sizeof(charmap) / 2]; 93 | } 94 | 95 | *ptr = q; 96 | 97 | return (char) n; 98 | } 99 | 100 | char* FAST_FUNC strcpy_and_process_escape_sequences(char *dst, const char *src) 101 | { 102 | while (1) { 103 | char c, c1; 104 | c = c1 = *src++; 105 | if (c1 == '\\') 106 | c1 = bb_process_escape_sequence(&src); 107 | *dst = c1; 108 | if (c == '\0') 109 | return dst; 110 | dst++; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /busybox/libbb/read.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | #include "libbb.h" 10 | 11 | ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count) 12 | { 13 | ssize_t n; 14 | 15 | do { 16 | n = read(fd, buf, count); 17 | } while (n < 0 && errno == EINTR); 18 | 19 | return n; 20 | } 21 | 22 | /* 23 | * Read all of the supplied buffer from a file. 24 | * This does multiple reads as necessary. 25 | * Returns the amount read, or -1 on an error. 26 | * A short read is returned on an end of file. 27 | */ 28 | ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len) 29 | { 30 | ssize_t cc; 31 | ssize_t total; 32 | 33 | total = 0; 34 | 35 | while (len) { 36 | cc = safe_read(fd, buf, len); 37 | 38 | if (cc < 0) { 39 | if (total) { 40 | /* we already have some! */ 41 | /* user can do another read to know the error code */ 42 | return total; 43 | } 44 | return cc; /* read() returns -1 on failure. */ 45 | } 46 | if (cc == 0) 47 | break; 48 | buf = ((char *)buf) + cc; 49 | total += cc; 50 | len -= cc; 51 | } 52 | 53 | return total; 54 | } 55 | 56 | ssize_t FAST_FUNC read_close(int fd, void *buf, size_t size) 57 | { 58 | /*int e;*/ 59 | size = full_read(fd, buf, size); 60 | /*e = errno;*/ 61 | close(fd); 62 | /*errno = e;*/ 63 | return size; 64 | } 65 | 66 | ssize_t FAST_FUNC open_read_close(const char *filename, void *buf, size_t size) 67 | { 68 | int fd = open(filename, O_RDONLY); 69 | if (fd < 0) 70 | return fd; 71 | return read_close(fd, buf, size); 72 | } 73 | -------------------------------------------------------------------------------- /busybox/libbb/safe_write.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | ssize_t FAST_FUNC safe_write(int fd, const void *buf, size_t count) 13 | { 14 | ssize_t n; 15 | 16 | do { 17 | n = write(fd, buf, count); 18 | } while (n < 0 && errno == EINTR); 19 | 20 | return n; 21 | } 22 | -------------------------------------------------------------------------------- /busybox/libbb/skip_whitespace.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * skip_whitespace implementation for busybox 4 | * 5 | * Copyright (C) 2003 Manuel Novoa III 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | char* FAST_FUNC skip_whitespace(const char *s) 13 | { 14 | /* In POSIX/C locale (the only locale we care about: do we REALLY want 15 | * to allow Unicode whitespace in, say, .conf files? nuts!) 16 | * isspace is only these chars: "\t\n\v\f\r" and space. 17 | * "\t\n\v\f\r" happen to have ASCII codes 9,10,11,12,13. 18 | * Use that. 19 | */ 20 | while (*s == ' ' || (unsigned char)(*s - 9) <= (13 - 9)) 21 | s++; 22 | 23 | return (char *) s; 24 | } 25 | 26 | #if 0 27 | 28 | char* FAST_FUNC skip_non_whitespace(const char *s) 29 | { 30 | while (*s != '\0' && *s != ' ' && (unsigned char)(*s - 9) > (13 - 9)) 31 | s++; 32 | 33 | return (char *) s; 34 | } 35 | 36 | char* FAST_FUNC skip_dev_pfx(const char *tty_name) 37 | { 38 | if (strncmp(tty_name, "/dev/", 5) == 0) 39 | tty_name += 5; 40 | return (char*)tty_name; 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /busybox/libbb/verror_msg.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | #include "libbb.h" 10 | #if ENABLE_FEATURE_SYSLOG 11 | # include 12 | #endif 13 | 14 | smallint logmode = LOGMODE_STDIO; 15 | const char *msg_eol = "\n"; 16 | 17 | void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) 18 | { 19 | char *msg, *msg1; 20 | int applet_len, strerr_len, msgeol_len, used; 21 | 22 | if (!logmode) 23 | return; 24 | 25 | if (!s) /* nomsg[_and_die] uses NULL fmt */ 26 | s = ""; /* some libc don't like printf(NULL) */ 27 | 28 | used = vasprintf(&msg, s, p); 29 | if (used < 0) 30 | return; 31 | 32 | /* This is ugly and costs +60 bytes compared to multiple 33 | * fprintf's, but is guaranteed to do a single write. 34 | * This is needed for e.g. httpd logging, when multiple 35 | * children can produce log messages simultaneously. */ 36 | 37 | applet_len = strlen(applet_name) + 2; /* "applet: " */ 38 | strerr_len = strerr ? strlen(strerr) : 0; 39 | msgeol_len = strlen(msg_eol); 40 | /* can't use xrealloc: it calls error_msg on failure, 41 | * that may result in a recursion */ 42 | /* +3 is for ": " before strerr and for terminating NUL */ 43 | msg1 = realloc(msg, applet_len + used + strerr_len + msgeol_len + 3); 44 | if (!msg1) { 45 | msg[used++] = '\n'; /* overwrites NUL */ 46 | applet_len = 0; 47 | } else { 48 | msg = msg1; 49 | /* TODO: maybe use writev instead of memmoving? Need full_writev? */ 50 | memmove(msg + applet_len, msg, used); 51 | used += applet_len; 52 | strcpy(msg, applet_name); 53 | msg[applet_len - 2] = ':'; 54 | msg[applet_len - 1] = ' '; 55 | if (strerr) { 56 | if (s[0]) { /* not perror_nomsg? */ 57 | msg[used++] = ':'; 58 | msg[used++] = ' '; 59 | } 60 | strcpy(&msg[used], strerr); 61 | used += strerr_len; 62 | } 63 | strcpy(&msg[used], msg_eol); 64 | used += msgeol_len; 65 | } 66 | 67 | if (logmode & LOGMODE_STDIO) { 68 | fflush_all(); 69 | full_write(STDERR_FILENO, msg, used); 70 | } 71 | #if ENABLE_FEATURE_SYSLOG 72 | if (logmode & LOGMODE_SYSLOG) { 73 | syslog(LOG_ERR, "%s", msg + applet_len); 74 | } 75 | #endif 76 | free(msg); 77 | } 78 | 79 | #ifdef VERSION_WITH_WRITEV 80 | /* Code size is approximately the same, but currently it's the only user 81 | * of writev in entire bbox. __libc_writev in uclibc is ~50 bytes. */ 82 | void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) 83 | { 84 | int strerr_len, msgeol_len; 85 | struct iovec iov[3]; 86 | 87 | #define used (iov[2].iov_len) 88 | #define msgv (iov[2].iov_base) 89 | #define msgc ((char*)(iov[2].iov_base)) 90 | #define msgptr (&(iov[2].iov_base)) 91 | 92 | if (!logmode) 93 | return; 94 | 95 | if (!s) /* nomsg[_and_die] uses NULL fmt */ 96 | s = ""; /* some libc don't like printf(NULL) */ 97 | 98 | /* Prevent "derefing type-punned ptr will break aliasing rules" */ 99 | used = vasprintf((char**)(void*)msgptr, s, p); 100 | if (used < 0) 101 | return; 102 | 103 | /* This is ugly and costs +60 bytes compared to multiple 104 | * fprintf's, but is guaranteed to do a single write. 105 | * This is needed for e.g. httpd logging, when multiple 106 | * children can produce log messages simultaneously. */ 107 | 108 | strerr_len = strerr ? strlen(strerr) : 0; 109 | msgeol_len = strlen(msg_eol); 110 | /* +3 is for ": " before strerr and for terminating NUL */ 111 | msgv = xrealloc(msgv, used + strerr_len + msgeol_len + 3); 112 | if (strerr) { 113 | msgc[used++] = ':'; 114 | msgc[used++] = ' '; 115 | strcpy(msgc + used, strerr); 116 | used += strerr_len; 117 | } 118 | strcpy(msgc + used, msg_eol); 119 | used += msgeol_len; 120 | 121 | if (logmode & LOGMODE_STDIO) { 122 | iov[0].iov_base = (char*)applet_name; 123 | iov[0].iov_len = strlen(applet_name); 124 | iov[1].iov_base = (char*)": "; 125 | iov[1].iov_len = 2; 126 | /*iov[2].iov_base = msgc;*/ 127 | /*iov[2].iov_len = used;*/ 128 | fflush_all(); 129 | writev(STDERR_FILENO, iov, 3); 130 | } 131 | # if ENABLE_FEATURE_SYSLOG 132 | if (logmode & LOGMODE_SYSLOG) { 133 | syslog(LOG_ERR, "%s", msgc); 134 | } 135 | # endif 136 | free(msgc); 137 | } 138 | #endif 139 | 140 | 141 | void FAST_FUNC bb_error_msg_and_die(const char *s, ...) 142 | { 143 | va_list p; 144 | 145 | va_start(p, s); 146 | bb_verror_msg(s, p, NULL); 147 | va_end(p); 148 | xfunc_die(); 149 | } 150 | 151 | void FAST_FUNC bb_error_msg(const char *s, ...) 152 | { 153 | va_list p; 154 | 155 | va_start(p, s); 156 | bb_verror_msg(s, p, NULL); 157 | va_end(p); 158 | } 159 | -------------------------------------------------------------------------------- /busybox/libbb/wfopen.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | FILE* FAST_FUNC fopen_or_warn(const char *path, const char *mode) 13 | { 14 | FILE *fp = fopen(path, mode); 15 | if (!fp) { 16 | bb_simple_perror_msg(path); 17 | //errno = 0; /* why? */ 18 | } 19 | return fp; 20 | } 21 | 22 | FILE* FAST_FUNC fopen_for_read(const char *path) 23 | { 24 | return fopen(path, "r"); 25 | } 26 | 27 | FILE* FAST_FUNC xfopen_for_read(const char *path) 28 | { 29 | return xfopen(path, "r"); 30 | } 31 | 32 | FILE* FAST_FUNC fopen_for_write(const char *path) 33 | { 34 | return fopen(path, "w"); 35 | } 36 | 37 | FILE* FAST_FUNC xfopen_for_write(const char *path) 38 | { 39 | return xfopen(path, "w"); 40 | } 41 | 42 | static FILE* xfdopen_helper(unsigned fd_and_rw_bit) 43 | { 44 | FILE* fp = fdopen(fd_and_rw_bit >> 1, fd_and_rw_bit & 1 ? "w" : "r"); 45 | if (!fp) 46 | bb_error_msg_and_die("%s", bb_msg_memory_exhausted); 47 | return fp; 48 | } 49 | FILE* FAST_FUNC xfdopen_for_read(int fd) 50 | { 51 | return xfdopen_helper(fd << 1); 52 | } 53 | FILE* FAST_FUNC xfdopen_for_write(int fd) 54 | { 55 | return xfdopen_helper((fd << 1) + 1); 56 | } 57 | -------------------------------------------------------------------------------- /busybox/libbb/wfopen_input.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * wfopen_input implementation for busybox 4 | * 5 | * Copyright (C) 2003 Manuel Novoa III 6 | * 7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 | */ 9 | 10 | /* A number of applets need to open a file for reading, where the filename 11 | * is a command line arg. Since often that arg is '-' (meaning stdin), 12 | * we avoid testing everywhere by consolidating things in this routine. 13 | */ 14 | 15 | #include "libbb.h" 16 | 17 | FILE* FAST_FUNC fopen_or_warn_stdin(const char *filename) 18 | { 19 | FILE *fp = stdin; 20 | 21 | if (filename != bb_msg_standard_input 22 | && NOT_LONE_DASH(filename) 23 | ) { 24 | fp = fopen_or_warn(filename, "r"); 25 | } 26 | return fp; 27 | } 28 | 29 | FILE* FAST_FUNC xfopen_stdin(const char *filename) 30 | { 31 | FILE *fp = fopen_or_warn_stdin(filename); 32 | if (fp) 33 | return fp; 34 | xfunc_die(); /* We already output an error message. */ 35 | return 0; 36 | } 37 | 38 | #if 0 39 | 40 | int FAST_FUNC open_or_warn_stdin(const char *filename) 41 | { 42 | int fd = STDIN_FILENO; 43 | 44 | if (filename != bb_msg_standard_input 45 | && NOT_LONE_DASH(filename) 46 | ) { 47 | fd = open_or_warn(filename, O_RDONLY); 48 | } 49 | 50 | return fd; 51 | } 52 | 53 | int FAST_FUNC xopen_stdin(const char *filename) 54 | { 55 | int fd = open_or_warn_stdin(filename); 56 | if (fd >= 0) 57 | return fd; 58 | xfunc_die(); /* We already output an error message. */ 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /busybox/libbb/xatonum.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * ascii-to-numbers implementations for busybox 4 | * 5 | * Copyright (C) 2003 Manuel Novoa III 6 | * 7 | * Licensed under GPLv2, see file LICENSE in this source tree. 8 | */ 9 | 10 | #include "libbb.h" 11 | 12 | #define type long long 13 | #define xstrtou(rest) xstrtoull##rest 14 | #define xstrto(rest) xstrtoll##rest 15 | #define xatou(rest) xatoull##rest 16 | #define xato(rest) xatoll##rest 17 | #define XSTR_UTYPE_MAX ULLONG_MAX 18 | #define XSTR_TYPE_MAX LLONG_MAX 19 | #define XSTR_TYPE_MIN LLONG_MIN 20 | #define XSTR_STRTOU strtoull 21 | #include "xatonum_template.c" 22 | 23 | #if ULONG_MAX != ULLONG_MAX 24 | #define type long 25 | #define xstrtou(rest) xstrtoul##rest 26 | #define xstrto(rest) xstrtol##rest 27 | #define xatou(rest) xatoul##rest 28 | #define xato(rest) xatol##rest 29 | #define XSTR_UTYPE_MAX ULONG_MAX 30 | #define XSTR_TYPE_MAX LONG_MAX 31 | #define XSTR_TYPE_MIN LONG_MIN 32 | #define XSTR_STRTOU strtoul 33 | #include "xatonum_template.c" 34 | #endif 35 | 36 | #if UINT_MAX != ULONG_MAX 37 | static ALWAYS_INLINE 38 | unsigned bb_strtoui(const char *str, char **end, int b) 39 | { 40 | unsigned long v = strtoul(str, end, b); 41 | if (v > UINT_MAX) { 42 | errno = ERANGE; 43 | return UINT_MAX; 44 | } 45 | return v; 46 | } 47 | #define type int 48 | #define xstrtou(rest) xstrtou##rest 49 | #define xstrto(rest) xstrtoi##rest 50 | #define xatou(rest) xatou##rest 51 | #define xato(rest) xatoi##rest 52 | #define XSTR_UTYPE_MAX UINT_MAX 53 | #define XSTR_TYPE_MAX INT_MAX 54 | #define XSTR_TYPE_MIN INT_MIN 55 | /* libc has no strtoui, so we need to create/use our own */ 56 | #define XSTR_STRTOU bb_strtoui 57 | #include "xatonum_template.c" 58 | #endif 59 | 60 | /* A few special cases */ 61 | 62 | int FAST_FUNC xatoi_positive(const char *numstr) 63 | { 64 | return xatou_range(numstr, 0, INT_MAX); 65 | } 66 | 67 | uint16_t FAST_FUNC xatou16(const char *numstr) 68 | { 69 | return xatou_range(numstr, 0, 0xffff); 70 | } 71 | -------------------------------------------------------------------------------- /busybox/libbb/xatonum_template.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Licensed under GPLv2, see file LICENSE in this source tree. 4 | */ 5 | /* 6 | You need to define the following (example): 7 | 8 | #define type long 9 | #define xstrtou(rest) xstrtoul##rest 10 | #define xstrto(rest) xstrtol##rest 11 | #define xatou(rest) xatoul##rest 12 | #define xato(rest) xatol##rest 13 | #define XSTR_UTYPE_MAX ULONG_MAX 14 | #define XSTR_TYPE_MAX LONG_MAX 15 | #define XSTR_TYPE_MIN LONG_MIN 16 | #define XSTR_STRTOU strtoul 17 | */ 18 | 19 | unsigned type FAST_FUNC xstrtou(_range_sfx)(const char *numstr, int base, 20 | unsigned type lower, 21 | unsigned type upper, 22 | const struct suffix_mult *suffixes) 23 | { 24 | unsigned type r; 25 | int old_errno; 26 | char *e; 27 | 28 | /* Disallow '-' and any leading whitespace. */ 29 | if (*numstr == '-' || *numstr == '+' || isspace(*numstr)) 30 | goto inval; 31 | 32 | /* Since this is a lib function, we're not allowed to reset errno to 0. 33 | * Doing so could break an app that is deferring checking of errno. 34 | * So, save the old value so that we can restore it if successful. */ 35 | old_errno = errno; 36 | errno = 0; 37 | r = XSTR_STRTOU(numstr, &e, base); 38 | /* Do the initial validity check. Note: The standards do not 39 | * guarantee that errno is set if no digits were found. So we 40 | * must test for this explicitly. */ 41 | if (errno || numstr == e) 42 | goto inval; /* error / no digits / illegal trailing chars */ 43 | 44 | errno = old_errno; /* Ok. So restore errno. */ 45 | 46 | /* Do optional suffix parsing. Allow 'empty' suffix tables. 47 | * Note that we also allow nul suffixes with associated multipliers, 48 | * to allow for scaling of the numstr by some default multiplier. */ 49 | if (suffixes) { 50 | while (suffixes->mult) { 51 | if (strcmp(suffixes->suffix, e) == 0) { 52 | if (XSTR_UTYPE_MAX / suffixes->mult < r) 53 | goto range; /* overflow! */ 54 | r *= suffixes->mult; 55 | goto chk_range; 56 | } 57 | ++suffixes; 58 | } 59 | } 60 | 61 | /* Note: trailing space is an error. 62 | It would be easy enough to allow though if desired. */ 63 | if (*e) 64 | goto inval; 65 | chk_range: 66 | /* Finally, check for range limits. */ 67 | if (r >= lower && r <= upper) 68 | return r; 69 | range: 70 | bb_error_msg_and_die("number %s is not in %llu..%llu range", 71 | numstr, (unsigned long long)lower, 72 | (unsigned long long)upper); 73 | inval: 74 | bb_error_msg_and_die("invalid number '%s'", numstr); 75 | } 76 | 77 | unsigned type FAST_FUNC xstrtou(_range)(const char *numstr, int base, 78 | unsigned type lower, 79 | unsigned type upper) 80 | { 81 | return xstrtou(_range_sfx)(numstr, base, lower, upper, NULL); 82 | } 83 | 84 | unsigned type FAST_FUNC xstrtou(_sfx)(const char *numstr, int base, 85 | const struct suffix_mult *suffixes) 86 | { 87 | return xstrtou(_range_sfx)(numstr, base, 0, XSTR_UTYPE_MAX, suffixes); 88 | } 89 | 90 | unsigned type FAST_FUNC xstrtou()(const char *numstr, int base) 91 | { 92 | return xstrtou(_range_sfx)(numstr, base, 0, XSTR_UTYPE_MAX, NULL); 93 | } 94 | 95 | unsigned type FAST_FUNC xatou(_range_sfx)(const char *numstr, 96 | unsigned type lower, 97 | unsigned type upper, 98 | const struct suffix_mult *suffixes) 99 | { 100 | return xstrtou(_range_sfx)(numstr, 10, lower, upper, suffixes); 101 | } 102 | 103 | unsigned type FAST_FUNC xatou(_range)(const char *numstr, 104 | unsigned type lower, 105 | unsigned type upper) 106 | { 107 | return xstrtou(_range_sfx)(numstr, 10, lower, upper, NULL); 108 | } 109 | 110 | unsigned type FAST_FUNC xatou(_sfx)(const char *numstr, 111 | const struct suffix_mult *suffixes) 112 | { 113 | return xstrtou(_range_sfx)(numstr, 10, 0, XSTR_UTYPE_MAX, suffixes); 114 | } 115 | 116 | unsigned type FAST_FUNC xatou()(const char *numstr) 117 | { 118 | return xatou(_sfx)(numstr, NULL); 119 | } 120 | 121 | /* Signed ones */ 122 | 123 | type FAST_FUNC xstrto(_range_sfx)(const char *numstr, int base, 124 | type lower, 125 | type upper, 126 | const struct suffix_mult *suffixes) 127 | { 128 | unsigned type u = XSTR_TYPE_MAX; 129 | type r; 130 | const char *p = numstr; 131 | 132 | /* NB: if you'll decide to disallow '+': 133 | * at least renice applet needs to allow it */ 134 | if (p[0] == '+' || p[0] == '-') { 135 | ++p; 136 | if (p[0] == '-') 137 | ++u; /* = _MIN (01111... + 1 == 10000...) */ 138 | } 139 | 140 | r = xstrtou(_range_sfx)(p, base, 0, u, suffixes); 141 | 142 | if (*numstr == '-') { 143 | r = -r; 144 | } 145 | 146 | if (r < lower || r > upper) { 147 | bb_error_msg_and_die("number %s is not in %lld..%lld range", 148 | numstr, (long long)lower, (long long)upper); 149 | } 150 | 151 | return r; 152 | } 153 | 154 | type FAST_FUNC xstrto(_range)(const char *numstr, int base, type lower, type upper) 155 | { 156 | return xstrto(_range_sfx)(numstr, base, lower, upper, NULL); 157 | } 158 | 159 | type FAST_FUNC xstrto()(const char *numstr, int base) 160 | { 161 | return xstrto(_range_sfx)(numstr, base, XSTR_TYPE_MIN, XSTR_TYPE_MAX, NULL); 162 | } 163 | 164 | type FAST_FUNC xato(_range_sfx)(const char *numstr, 165 | type lower, 166 | type upper, 167 | const struct suffix_mult *suffixes) 168 | { 169 | return xstrto(_range_sfx)(numstr, 10, lower, upper, suffixes); 170 | } 171 | 172 | type FAST_FUNC xato(_range)(const char *numstr, type lower, type upper) 173 | { 174 | return xstrto(_range_sfx)(numstr, 10, lower, upper, NULL); 175 | } 176 | 177 | type FAST_FUNC xato(_sfx)(const char *numstr, const struct suffix_mult *suffixes) 178 | { 179 | return xstrto(_range_sfx)(numstr, 10, XSTR_TYPE_MIN, XSTR_TYPE_MAX, suffixes); 180 | } 181 | 182 | type FAST_FUNC xato()(const char *numstr) 183 | { 184 | return xstrto(_range_sfx)(numstr, 10, XSTR_TYPE_MIN, XSTR_TYPE_MAX, NULL); 185 | } 186 | 187 | #undef type 188 | #undef xstrtou 189 | #undef xstrto 190 | #undef xatou 191 | #undef xato 192 | #undef XSTR_UTYPE_MAX 193 | #undef XSTR_TYPE_MAX 194 | #undef XSTR_TYPE_MIN 195 | #undef XSTR_STRTOU 196 | -------------------------------------------------------------------------------- /busybox/libbb/xfunc_die.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 2008 by Denys Vlasenko 6 | * 7 | * Licensed under GPLv2, see file LICENSE in this source tree. 8 | */ 9 | 10 | /* Keeping it separate allows to NOT suck in stdio for VERY small applets. 11 | * Try building busybox with only "true" enabled... */ 12 | 13 | #include "libbb.h" 14 | 15 | int die_sleep; 16 | #if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH 17 | jmp_buf die_jmp; 18 | #endif 19 | 20 | void FAST_FUNC xfunc_die(void) 21 | { 22 | if (die_sleep) { 23 | if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH) 24 | && die_sleep < 0 25 | ) { 26 | /* Special case. We arrive here if NOFORK applet 27 | * calls xfunc, which then decides to die. 28 | * We don't die, but jump instead back to caller. 29 | * NOFORK applets still cannot carelessly call xfuncs: 30 | * p = xmalloc(10); 31 | * q = xmalloc(10); // BUG! if this dies, we leak p! 32 | */ 33 | /* -2222 means "zero" (longjmp can't pass 0) 34 | * run_nofork_applet() catches -2222. */ 35 | // longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222); 36 | } 37 | sleep(die_sleep); 38 | } 39 | exit(EXIT_FAILURE); 40 | } 41 | -------------------------------------------------------------------------------- /busybox/libbb/xfuncs.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * Copyright (C) 2006 Rob Landley 7 | * Copyright (C) 2006 Denys Vlasenko 8 | * 9 | * Licensed under GPLv2, see file LICENSE in this source tree. 10 | */ 11 | 12 | /* We need to have separate xfuncs.c and xfuncs_printf.c because 13 | * with current linkers, even with section garbage collection, 14 | * if *.o module references any of XXXprintf functions, you pull in 15 | * entire printf machinery. Even if you do not use the function 16 | * which uses XXXprintf. 17 | * 18 | * xfuncs.c contains functions (not necessarily xfuncs) 19 | * which do not pull in printf, directly or indirectly. 20 | * xfunc_printf.c contains those which do. 21 | * 22 | * TODO: move xmalloc() and xatonum() here. 23 | */ 24 | 25 | #include "libbb.h" 26 | 27 | /* Turn on nonblocking I/O on a fd */ 28 | void FAST_FUNC ndelay_on(int fd) 29 | { 30 | int flags = fcntl(fd, F_GETFL); 31 | if (flags & O_NONBLOCK) 32 | return; 33 | fcntl(fd, F_SETFL, flags | O_NONBLOCK); 34 | } 35 | 36 | void FAST_FUNC ndelay_off(int fd) 37 | { 38 | int flags = fcntl(fd, F_GETFL); 39 | if (!(flags & O_NONBLOCK)) 40 | return; 41 | fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 42 | } 43 | 44 | void FAST_FUNC close_on_exec_on(int fd) 45 | { 46 | fcntl(fd, F_SETFD, FD_CLOEXEC); 47 | } 48 | 49 | char* FAST_FUNC strncpy_IFNAMSIZ(char *dst, const char *src) 50 | { 51 | #ifndef IFNAMSIZ 52 | enum { IFNAMSIZ = 16 }; 53 | #endif 54 | return strncpy(dst, src, IFNAMSIZ); 55 | } 56 | 57 | 58 | /* Convert unsigned integer to ascii, writing into supplied buffer. 59 | * A truncated result contains the first few digits of the result ala strncpy. 60 | * Returns a pointer past last generated digit, does _not_ store NUL. 61 | */ 62 | void BUG_sizeof(void); 63 | char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen) 64 | { 65 | unsigned i, out, res; 66 | 67 | if (buflen) { 68 | out = 0; 69 | if (sizeof(n) == 4) 70 | // 2^32-1 = 4294967295 71 | i = 1000000000; 72 | #if UINT_MAX > 4294967295 /* prevents warning about "const too large" */ 73 | else 74 | if (sizeof(n) == 8) 75 | // 2^64-1 = 18446744073709551615 76 | i = 10000000000000000000; 77 | #endif 78 | else 79 | BUG_sizeof(); 80 | for (; i; i /= 10) { 81 | res = n / i; 82 | n = n % i; 83 | if (res || out || i == 1) { 84 | if (--buflen == 0) 85 | break; 86 | out++; 87 | *buf++ = '0' + res; 88 | } 89 | } 90 | } 91 | return buf; 92 | } 93 | 94 | /* Convert signed integer to ascii, like utoa_to_buf() */ 95 | char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen) 96 | { 97 | if (!buflen) 98 | return buf; 99 | if (n < 0) { 100 | n = -n; 101 | *buf++ = '-'; 102 | buflen--; 103 | } 104 | return utoa_to_buf((unsigned)n, buf, buflen); 105 | } 106 | 107 | // The following two functions use a static buffer, so calling either one a 108 | // second time will overwrite previous results. 109 | // 110 | // The largest 32 bit integer is -2 billion plus NUL, or 1+10+1=12 bytes. 111 | // It so happens that sizeof(int) * 3 is enough for 32+ bit ints. 112 | // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit) 113 | 114 | static char local_buf[sizeof(int) * 3]; 115 | 116 | /* Convert unsigned integer to ascii using a static buffer (returned). */ 117 | char* FAST_FUNC utoa(unsigned n) 118 | { 119 | *(utoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0'; 120 | 121 | return local_buf; 122 | } 123 | 124 | /* Convert signed integer to ascii using a static buffer (returned). */ 125 | char* FAST_FUNC itoa(int n) 126 | { 127 | *(itoa_to_buf(n, local_buf, sizeof(local_buf) - 1)) = '\0'; 128 | 129 | return local_buf; 130 | } 131 | 132 | /* Emit a string of hex representation of bytes */ 133 | char* FAST_FUNC bin2hex(char *p, const char *cp, int count) 134 | { 135 | while (count) { 136 | unsigned char c = *cp++; 137 | /* put lowercase hex digits */ 138 | *p++ = 0x20 | bb_hexdigits_upcase[c >> 4]; 139 | *p++ = 0x20 | bb_hexdigits_upcase[c & 0xf]; 140 | count--; 141 | } 142 | return p; 143 | } 144 | 145 | /* Convert "[x]x[:][x]x[:][x]x[:][x]x" hex string to binary, no more than COUNT bytes */ 146 | char* FAST_FUNC hex2bin(char *dst, const char *str, int count) 147 | { 148 | errno = EINVAL; 149 | while (*str && count) { 150 | uint8_t val; 151 | uint8_t c = *str++; 152 | if (isdigit(c)) 153 | val = c - '0'; 154 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 155 | val = (c|0x20) - ('a' - 10); 156 | else 157 | return NULL; 158 | val <<= 4; 159 | c = *str; 160 | if (isdigit(c)) 161 | val |= c - '0'; 162 | else if ((c|0x20) >= 'a' && (c|0x20) <= 'f') 163 | val |= (c|0x20) - ('a' - 10); 164 | else if (c == ':' || c == '\0') 165 | val >>= 4; 166 | else 167 | return NULL; 168 | 169 | *dst++ = val; 170 | if (c != '\0') 171 | str++; 172 | if (*str == ':') 173 | str++; 174 | count--; 175 | } 176 | errno = (*str ? ERANGE : 0); 177 | return dst; 178 | } 179 | 180 | /* Return how long the file at fd is, if there's any way to determine it. */ 181 | #ifdef UNUSED 182 | off_t FAST_FUNC fdlength(int fd) 183 | { 184 | off_t bottom = 0, top = 0, pos; 185 | long size; 186 | 187 | // If the ioctl works for this, return it. 188 | 189 | if (ioctl(fd, BLKGETSIZE, &size) >= 0) return size*512; 190 | 191 | // FIXME: explain why lseek(SEEK_END) is not used here! 192 | 193 | // If not, do a binary search for the last location we can read. (Some 194 | // block devices don't do BLKGETSIZE right.) 195 | 196 | do { 197 | char temp; 198 | 199 | pos = bottom + (top - bottom) / 2; 200 | 201 | // If we can read from the current location, it's bigger. 202 | 203 | if (lseek(fd, pos, SEEK_SET)>=0 && safe_read(fd, &temp, 1)==1) { 204 | if (bottom == top) bottom = top = (top+1) * 2; 205 | else bottom = pos; 206 | 207 | // If we can't, it's smaller. 208 | 209 | } else { 210 | if (bottom == top) { 211 | if (!top) return 0; 212 | bottom = top/2; 213 | } 214 | else top = pos; 215 | } 216 | } while (bottom + 1 != top); 217 | 218 | return pos + 1; 219 | } 220 | #endif 221 | 222 | int FAST_FUNC bb_putchar_stderr(char ch) 223 | { 224 | return write(STDERR_FILENO, &ch, 1); 225 | } 226 | 227 | ssize_t FAST_FUNC full_write1_str(const char *str) 228 | { 229 | return full_write(STDOUT_FILENO, str, strlen(str)); 230 | } 231 | 232 | ssize_t FAST_FUNC full_write2_str(const char *str) 233 | { 234 | return full_write(STDERR_FILENO, str, strlen(str)); 235 | } 236 | 237 | static int wh_helper(int value, int def_val, const char *env_name, int *err) 238 | { 239 | if (value == 0) { 240 | char *s = getenv(env_name); 241 | if (s) { 242 | value = atoi(s); 243 | /* If LINES/COLUMNS are set, pretend that there is 244 | * no error getting w/h, this prevents some ugly 245 | * cursor tricks by our callers */ 246 | *err = 0; 247 | } 248 | } 249 | if (value <= 1 || value >= 30000) 250 | value = def_val; 251 | return value; 252 | } 253 | 254 | #if 0 255 | /* It is perfectly ok to pass in a NULL for either width or for 256 | * height, in which case that value will not be set. */ 257 | int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height) 258 | { 259 | struct winsize win; 260 | int err; 261 | 262 | win.ws_row = 0; 263 | win.ws_col = 0; 264 | /* I've seen ioctl returning 0, but row/col is (still?) 0. 265 | * We treat that as an error too. */ 266 | err = ioctl(fd, TIOCGWINSZ, &win) != 0 || win.ws_row == 0; 267 | if (height) 268 | *height = wh_helper(win.ws_row, 24, "LINES", &err); 269 | if (width) 270 | *width = wh_helper(win.ws_col, 80, "COLUMNS", &err); 271 | return err; 272 | } 273 | #endif 274 | 275 | #if 0 276 | int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) 277 | { 278 | return tcsetattr(STDIN_FILENO, TCSANOW, tp); 279 | } 280 | #endif 281 | 282 | #if 0 283 | pid_t FAST_FUNC safe_waitpid(pid_t pid, int *wstat, int options) 284 | { 285 | pid_t r; 286 | 287 | do 288 | r = waitpid(pid, wstat, options); 289 | while ((r == -1) && (errno == EINTR)); 290 | return r; 291 | } 292 | #endif 293 | 294 | #if 0 295 | pid_t FAST_FUNC wait_any_nohang(int *wstat) 296 | { 297 | return safe_waitpid(-1, wstat, WNOHANG); 298 | } 299 | #endif 300 | 301 | #if 0 302 | // Wait for the specified child PID to exit, returning child's error return. 303 | int FAST_FUNC wait4pid(pid_t pid) 304 | { 305 | int status; 306 | 307 | if (pid <= 0) { 308 | /*errno = ECHILD; -- wrong. */ 309 | /* we expect errno to be already set from failed [v]fork/exec */ 310 | return -1; 311 | } 312 | if (safe_waitpid(pid, &status, 0) == -1) 313 | return -1; 314 | if (WIFEXITED(status)) 315 | return WEXITSTATUS(status); 316 | if (WIFSIGNALED(status)) 317 | return WTERMSIG(status) + 0x180; 318 | return 0; 319 | } 320 | #endif 321 | -------------------------------------------------------------------------------- /busybox/libbb/xfuncs_printf.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) 1999-2004 by Erik Andersen 6 | * Copyright (C) 2006 Rob Landley 7 | * Copyright (C) 2006 Denys Vlasenko 8 | * 9 | * Licensed under GPLv2, see file LICENSE in this source tree. 10 | */ 11 | 12 | /* We need to have separate xfuncs.c and xfuncs_printf.c because 13 | * with current linkers, even with section garbage collection, 14 | * if *.o module references any of XXXprintf functions, you pull in 15 | * entire printf machinery. Even if you do not use the function 16 | * which uses XXXprintf. 17 | * 18 | * xfuncs.c contains functions (not necessarily xfuncs) 19 | * which do not pull in printf, directly or indirectly. 20 | * xfunc_printf.c contains those which do. 21 | */ 22 | 23 | #include "libbb.h" 24 | 25 | 26 | /* All the functions starting with "x" call bb_error_msg_and_die() if they 27 | * fail, so callers never need to check for errors. If it returned, it 28 | * succeeded. */ 29 | 30 | #ifndef DMALLOC 31 | /* dmalloc provides variants of these that do abort() on failure. 32 | * Since dmalloc's prototypes overwrite the impls here as they are 33 | * included after these prototypes in libbb.h, all is well. 34 | */ 35 | // Warn if we can't allocate size bytes of memory. 36 | void* FAST_FUNC malloc_or_warn(size_t size) 37 | { 38 | void *ptr = malloc(size); 39 | if (ptr == NULL && size != 0) 40 | bb_error_msg("%s", bb_msg_memory_exhausted); 41 | return ptr; 42 | } 43 | 44 | // Die if we can't allocate size bytes of memory. 45 | void* FAST_FUNC xmalloc(size_t size) 46 | { 47 | void *ptr = malloc(size); 48 | if (ptr == NULL && size != 0) 49 | bb_error_msg_and_die("%s", bb_msg_memory_exhausted); 50 | return ptr; 51 | } 52 | 53 | // Die if we can't resize previously allocated memory. (This returns a pointer 54 | // to the new memory, which may or may not be the same as the old memory. 55 | // It'll copy the contents to a new chunk and free the old one if necessary.) 56 | void* FAST_FUNC xrealloc(void *ptr, size_t size) 57 | { 58 | ptr = realloc(ptr, size); 59 | if (ptr == NULL && size != 0) 60 | bb_error_msg_and_die("%s", bb_msg_memory_exhausted); 61 | return ptr; 62 | } 63 | #endif /* DMALLOC */ 64 | 65 | // Die if we can't allocate and zero size bytes of memory. 66 | void* FAST_FUNC xzalloc(size_t size) 67 | { 68 | void *ptr = xmalloc(size); 69 | memset(ptr, 0, size); 70 | return ptr; 71 | } 72 | 73 | // Die if we can't copy a string to freshly allocated memory. 74 | char* FAST_FUNC xstrdup(const char *s) 75 | { 76 | char *t; 77 | 78 | if (s == NULL) 79 | return NULL; 80 | 81 | t = strdup(s); 82 | 83 | if (t == NULL) 84 | bb_error_msg_and_die("%s",bb_msg_memory_exhausted); 85 | 86 | return t; 87 | } 88 | 89 | // Die if we can't allocate n+1 bytes (space for the null terminator) and copy 90 | // the (possibly truncated to length n) string into it. 91 | char* FAST_FUNC xstrndup(const char *s, int n) 92 | { 93 | int m; 94 | char *t; 95 | 96 | if (ENABLE_DEBUG && s == NULL) 97 | bb_error_msg_and_die("xstrndup bug"); 98 | 99 | /* We can just xmalloc(n+1) and strncpy into it, */ 100 | /* but think about xstrndup("abc", 10000) wastage! */ 101 | m = n; 102 | t = (char*) s; 103 | while (m) { 104 | if (!*t) break; 105 | m--; 106 | t++; 107 | } 108 | n -= m; 109 | t = xmalloc(n + 1); 110 | t[n] = '\0'; 111 | 112 | return memcpy(t, s, n); 113 | } 114 | 115 | // Die if we can't open a file and return a FILE* to it. 116 | // Notice we haven't got xfread(), This is for use with fscanf() and friends. 117 | FILE* FAST_FUNC xfopen(const char *path, const char *mode) 118 | { 119 | FILE *fp = fopen(path, mode); 120 | if (fp == NULL) 121 | bb_perror_msg_and_die("can't open '%s'", path); 122 | return fp; 123 | } 124 | 125 | // Die if we can't open a file and return a fd. 126 | int FAST_FUNC xopen3(const char *pathname, int flags, int mode) 127 | { 128 | int ret; 129 | 130 | ret = open(pathname, flags, mode); 131 | if (ret < 0) { 132 | bb_perror_msg_and_die("can't open '%s'", pathname); 133 | } 134 | return ret; 135 | } 136 | 137 | // Die if we can't open a file and return a fd. 138 | int FAST_FUNC xopen(const char *pathname, int flags) 139 | { 140 | return xopen3(pathname, flags, 0666); 141 | } 142 | 143 | /* Die if we can't open an existing file readonly with O_NONBLOCK 144 | * and return the fd. 145 | * Note that for ioctl O_RDONLY is sufficient. 146 | */ 147 | int FAST_FUNC xopen_nonblocking(const char *pathname) 148 | { 149 | return xopen(pathname, O_RDONLY | O_NONBLOCK); 150 | } 151 | 152 | // Warn if we can't open a file and return a fd. 153 | int FAST_FUNC open3_or_warn(const char *pathname, int flags, int mode) 154 | { 155 | int ret; 156 | 157 | ret = open(pathname, flags, mode); 158 | if (ret < 0) { 159 | bb_perror_msg("can't open '%s'", pathname); 160 | } 161 | return ret; 162 | } 163 | 164 | // Warn if we can't open a file and return a fd. 165 | int FAST_FUNC open_or_warn(const char *pathname, int flags) 166 | { 167 | return open3_or_warn(pathname, flags, 0666); 168 | } 169 | 170 | void FAST_FUNC xunlink(const char *pathname) 171 | { 172 | if (unlink(pathname)) 173 | bb_perror_msg_and_die("can't remove file '%s'", pathname); 174 | } 175 | 176 | void FAST_FUNC xrename(const char *oldpath, const char *newpath) 177 | { 178 | if (rename(oldpath, newpath)) 179 | bb_perror_msg_and_die("can't move '%s' to '%s'", oldpath, newpath); 180 | } 181 | 182 | int FAST_FUNC rename_or_warn(const char *oldpath, const char *newpath) 183 | { 184 | int n = rename(oldpath, newpath); 185 | if (n) 186 | bb_perror_msg("can't move '%s' to '%s'", oldpath, newpath); 187 | return n; 188 | } 189 | 190 | void FAST_FUNC xpipe(int filedes[2]) 191 | { 192 | if (pipe(filedes)) 193 | bb_perror_msg_and_die("can't create pipe"); 194 | } 195 | 196 | void FAST_FUNC xdup2(int from, int to) 197 | { 198 | if (dup2(from, to) != to) 199 | bb_perror_msg_and_die("can't duplicate file descriptor"); 200 | } 201 | 202 | // "Renumber" opened fd 203 | void FAST_FUNC xmove_fd(int from, int to) 204 | { 205 | if (from == to) 206 | return; 207 | xdup2(from, to); 208 | close(from); 209 | } 210 | 211 | // Die with an error message if we can't write the entire buffer. 212 | void FAST_FUNC xwrite(int fd, const void *buf, size_t count) 213 | { 214 | if (count) { 215 | ssize_t size = full_write(fd, buf, count); 216 | if ((size_t)size != count) 217 | bb_error_msg_and_die("short write"); 218 | } 219 | } 220 | void FAST_FUNC xwrite_str(int fd, const char *str) 221 | { 222 | xwrite(fd, str, strlen(str)); 223 | } 224 | 225 | void FAST_FUNC xclose(int fd) 226 | { 227 | if (close(fd)) 228 | bb_perror_msg_and_die("close failed"); 229 | } 230 | 231 | // Die with an error message if we can't lseek to the right spot. 232 | off_t FAST_FUNC xlseek(int fd, off_t offset, int whence) 233 | { 234 | off_t off = lseek(fd, offset, whence); 235 | if (off == (off_t)-1) { 236 | if (whence == SEEK_SET) 237 | bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset); 238 | bb_perror_msg_and_die("lseek"); 239 | } 240 | return off; 241 | } 242 | 243 | int FAST_FUNC xmkstemp(char *template) 244 | { 245 | int fd = mkstemp(template); 246 | if (fd < 0) 247 | bb_perror_msg_and_die("can't create temp file '%s'", template); 248 | return fd; 249 | } 250 | 251 | // Die with supplied filename if this FILE* has ferror set. 252 | void FAST_FUNC die_if_ferror(FILE *fp, const char *fn) 253 | { 254 | if (ferror(fp)) { 255 | /* ferror doesn't set useful errno */ 256 | bb_error_msg_and_die("%s: I/O error", fn); 257 | } 258 | } 259 | 260 | // Die with an error message if stdout has ferror set. 261 | void FAST_FUNC die_if_ferror_stdout(void) 262 | { 263 | die_if_ferror(stdout, bb_msg_standard_output); 264 | } 265 | 266 | int FAST_FUNC fflush_all(void) 267 | { 268 | return fflush(NULL); 269 | } 270 | 271 | 272 | int FAST_FUNC bb_putchar(int ch) 273 | { 274 | return putchar(ch); 275 | } 276 | 277 | /* Die with an error message if we can't copy an entire FILE* to stdout, 278 | * then close that file. */ 279 | void FAST_FUNC xprint_and_close_file(FILE *file) 280 | { 281 | fflush_all(); 282 | // copyfd outputs error messages for us. 283 | if (bb_copyfd_eof(fileno(file), STDOUT_FILENO) == -1) 284 | xfunc_die(); 285 | 286 | fclose(file); 287 | } 288 | 289 | // Die with an error message if we can't malloc() enough space and do an 290 | // sprintf() into that space. 291 | char* FAST_FUNC xasprintf(const char *format, ...) 292 | { 293 | va_list p; 294 | int r; 295 | char *string_ptr; 296 | 297 | va_start(p, format); 298 | r = vasprintf(&string_ptr, format, p); 299 | va_end(p); 300 | 301 | if (r < 0) 302 | bb_error_msg_and_die("%s",bb_msg_memory_exhausted); 303 | return string_ptr; 304 | } 305 | 306 | void FAST_FUNC xsetenv(const char *key, const char *value) 307 | { 308 | if (setenv(key, value, 1)) 309 | bb_error_msg_and_die("%s",bb_msg_memory_exhausted); 310 | } 311 | 312 | /* Handles "VAR=VAL" strings, even those which are part of environ 313 | * _right now_ 314 | */ 315 | void FAST_FUNC bb_unsetenv(const char *var) 316 | { 317 | char *tp = strchr(var, '='); 318 | 319 | if (!tp) { 320 | unsetenv(var); 321 | return; 322 | } 323 | 324 | /* In case var was putenv'ed, we can't replace '=' 325 | * with NUL and unsetenv(var) - it won't work, 326 | * env is modified by the replacement, unsetenv 327 | * sees "VAR" instead of "VAR=VAL" and does not remove it! 328 | * horror :( */ 329 | tp = xstrndup(var, tp - var); 330 | unsetenv(tp); 331 | free(tp); 332 | } 333 | 334 | void FAST_FUNC bb_unsetenv_and_free(char *var) 335 | { 336 | bb_unsetenv(var); 337 | free(var); 338 | } 339 | 340 | // Die with an error message if we can't set gid. (Because resource limits may 341 | // limit this user to a given number of processes, and if that fills up the 342 | // setgid() will fail and we'll _still_be_root_, which is bad.) 343 | void FAST_FUNC xsetgid(gid_t gid) 344 | { 345 | if (setgid(gid)) bb_perror_msg_and_die("setgid"); 346 | } 347 | 348 | // Die with an error message if we can't set uid. (See xsetgid() for why.) 349 | void FAST_FUNC xsetuid(uid_t uid) 350 | { 351 | if (setuid(uid)) bb_perror_msg_and_die("setuid"); 352 | } 353 | 354 | // Die if we can't chdir to a new path. 355 | void FAST_FUNC xchdir(const char *path) 356 | { 357 | if (chdir(path)) 358 | bb_perror_msg_and_die("chdir(%s)", path); 359 | } 360 | 361 | void FAST_FUNC xchroot(const char *path) 362 | { 363 | // if (chroot(path)) 364 | // bb_perror_msg_and_die("can't change root directory to %s", path); 365 | xchdir("/"); 366 | } 367 | 368 | // Print a warning message if opendir() fails, but don't die. 369 | DIR* FAST_FUNC warn_opendir(const char *path) 370 | { 371 | DIR *dp; 372 | 373 | dp = opendir(path); 374 | if (!dp) 375 | bb_perror_msg("can't open '%s'", path); 376 | return dp; 377 | } 378 | 379 | // Die with an error message if opendir() fails. 380 | DIR* FAST_FUNC xopendir(const char *path) 381 | { 382 | DIR *dp; 383 | 384 | dp = opendir(path); 385 | if (!dp) 386 | bb_perror_msg_and_die("can't open '%s'", path); 387 | return dp; 388 | } 389 | 390 | // Die with an error message if we can't open a new socket. 391 | int FAST_FUNC xsocket(int domain, int type, int protocol) 392 | { 393 | int r = socket(domain, type, protocol); 394 | 395 | if (r < 0) { 396 | /* Hijack vaguely related config option */ 397 | #if ENABLE_VERBOSE_RESOLUTION_ERRORS 398 | const char *s = "INET"; 399 | # ifdef AF_PACKET 400 | if (domain == AF_PACKET) s = "PACKET"; 401 | # endif 402 | # ifdef AF_NETLINK 403 | if (domain == AF_NETLINK) s = "NETLINK"; 404 | # endif 405 | IF_FEATURE_IPV6(if (domain == AF_INET6) s = "INET6";) 406 | bb_perror_msg_and_die("socket(AF_%s,%d,%d)", s, type, protocol); 407 | #else 408 | bb_perror_msg_and_die("socket"); 409 | #endif 410 | } 411 | 412 | return r; 413 | } 414 | 415 | // Die with an error message if we can't bind a socket to an address. 416 | void FAST_FUNC xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) 417 | { 418 | if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind"); 419 | } 420 | 421 | // Die with an error message if we can't listen for connections on a socket. 422 | void FAST_FUNC xlisten(int s, int backlog) 423 | { 424 | if (listen(s, backlog)) bb_perror_msg_and_die("listen"); 425 | } 426 | 427 | /* Die with an error message if sendto failed. 428 | * Return bytes sent otherwise */ 429 | ssize_t FAST_FUNC xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, 430 | socklen_t tolen) 431 | { 432 | ssize_t ret = sendto(s, buf, len, 0, to, tolen); 433 | if (ret < 0) { 434 | if (ENABLE_FEATURE_CLEAN_UP) 435 | close(s); 436 | bb_perror_msg_and_die("sendto"); 437 | } 438 | return ret; 439 | } 440 | 441 | // xstat() - a stat() which dies on failure with meaningful error message 442 | void FAST_FUNC xstat(const char *name, struct stat *stat_buf) 443 | { 444 | if (stat(name, stat_buf)) 445 | bb_perror_msg_and_die("can't stat '%s'", name); 446 | } 447 | 448 | void FAST_FUNC xfstat(int fd, struct stat *stat_buf, const char *errmsg) 449 | { 450 | /* errmsg is usually a file name, but not always: 451 | * xfstat may be called in a spot where file name is no longer 452 | * available, and caller may give e.g. "can't stat input file" string. 453 | */ 454 | if (fstat(fd, stat_buf)) 455 | bb_simple_perror_msg_and_die(errmsg); 456 | } 457 | 458 | // selinux_or_die() - die if SELinux is disabled. 459 | void FAST_FUNC selinux_or_die(void) 460 | { 461 | #if ENABLE_SELINUX 462 | int rc = is_selinux_enabled(); 463 | if (rc == 0) { 464 | bb_error_msg_and_die("SELinux is disabled"); 465 | } else if (rc < 0) { 466 | bb_error_msg_and_die("is_selinux_enabled() failed"); 467 | } 468 | #else 469 | bb_error_msg_and_die("SELinux support is disabled"); 470 | #endif 471 | } 472 | 473 | int FAST_FUNC ioctl_or_perror_and_die(int fd, unsigned request, void *argp, const char *fmt,...) 474 | { 475 | int ret; 476 | va_list p; 477 | 478 | ret = ioctl(fd, request, argp); 479 | if (ret < 0) { 480 | va_start(p, fmt); 481 | bb_verror_msg(fmt, p, strerror(errno)); 482 | /* xfunc_die can actually longjmp, so be nice */ 483 | va_end(p); 484 | xfunc_die(); 485 | } 486 | return ret; 487 | } 488 | 489 | int FAST_FUNC ioctl_or_perror(int fd, unsigned request, void *argp, const char *fmt,...) 490 | { 491 | va_list p; 492 | int ret = ioctl(fd, request, argp); 493 | 494 | if (ret < 0) { 495 | va_start(p, fmt); 496 | bb_verror_msg(fmt, p, strerror(errno)); 497 | va_end(p); 498 | } 499 | return ret; 500 | } 501 | 502 | #if ENABLE_IOCTL_HEX2STR_ERROR 503 | int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp, const char *ioctl_name) 504 | { 505 | int ret; 506 | 507 | ret = ioctl(fd, request, argp); 508 | if (ret < 0) 509 | bb_simple_perror_msg(ioctl_name); 510 | return ret; 511 | } 512 | int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp, const char *ioctl_name) 513 | { 514 | int ret; 515 | 516 | ret = ioctl(fd, request, argp); 517 | if (ret < 0) 518 | bb_simple_perror_msg_and_die(ioctl_name); 519 | return ret; 520 | } 521 | #else 522 | int FAST_FUNC bb_ioctl_or_warn(int fd, unsigned request, void *argp) 523 | { 524 | int ret; 525 | 526 | ret = ioctl(fd, request, argp); 527 | if (ret < 0) 528 | bb_perror_msg("ioctl %#x failed", request); 529 | return ret; 530 | } 531 | int FAST_FUNC bb_xioctl(int fd, unsigned request, void *argp) 532 | { 533 | int ret; 534 | 535 | ret = ioctl(fd, request, argp); 536 | if (ret < 0) 537 | bb_perror_msg_and_die("ioctl %#x failed", request); 538 | return ret; 539 | } 540 | #endif 541 | 542 | char* FAST_FUNC xmalloc_ttyname(int fd) 543 | { 544 | char *buf = xzalloc(128); 545 | int r = ttyname_r(fd, buf, 127); 546 | if (r) { 547 | free(buf); 548 | buf = NULL; 549 | } 550 | return buf; 551 | } 552 | 553 | void FAST_FUNC generate_uuid(uint8_t *buf) 554 | { 555 | /* http://www.ietf.org/rfc/rfc4122.txt 556 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 557 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 558 | * | time_low | 559 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 560 | * | time_mid | time_hi_and_version | 561 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 562 | * |clk_seq_and_variant | node (0-1) | 563 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 564 | * | node (2-5) | 565 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 566 | * IOW, uuid has this layout: 567 | * uint32_t time_low (big endian) 568 | * uint16_t time_mid (big endian) 569 | * uint16_t time_hi_and_version (big endian) 570 | * version is a 4-bit field: 571 | * 1 Time-based 572 | * 2 DCE Security, with embedded POSIX UIDs 573 | * 3 Name-based (MD5) 574 | * 4 Randomly generated 575 | * 5 Name-based (SHA-1) 576 | * uint16_t clk_seq_and_variant (big endian) 577 | * variant is a 3-bit field: 578 | * 0xx Reserved, NCS backward compatibility 579 | * 10x The variant specified in rfc4122 580 | * 110 Reserved, Microsoft backward compatibility 581 | * 111 Reserved for future definition 582 | * uint8_t node[6] 583 | * 584 | * For version 4, these bits are set/cleared: 585 | * time_hi_and_version & 0x0fff | 0x4000 586 | * clk_seq_and_variant & 0x3fff | 0x8000 587 | */ 588 | pid_t pid; 589 | int i; 590 | 591 | i = open("/dev/urandom", O_RDONLY); 592 | if (i >= 0) { 593 | read(i, buf, 16); 594 | close(i); 595 | } 596 | /* Paranoia. /dev/urandom may be missing. 597 | * rand() is guaranteed to generate at least [0, 2^15) range, 598 | * but lowest bits in some libc are not so "random". */ 599 | //srand(monotonic_us()); /* pulls in printf */ 600 | srand(time(NULL)); /* pulls in printf */ 601 | pid = getpid(); 602 | while (1) { 603 | for (i = 0; i < 16; i++) 604 | buf[i] ^= rand() >> 5; 605 | if (pid == 0) 606 | break; 607 | srand(pid); 608 | pid = 0; 609 | } 610 | 611 | /* version = 4 */ 612 | buf[4 + 2 ] = (buf[4 + 2 ] & 0x0f) | 0x40; 613 | /* variant = 10x */ 614 | buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80; 615 | } 616 | 617 | #if BB_MMU 618 | pid_t FAST_FUNC xfork(void) 619 | { 620 | pid_t pid; 621 | pid = fork(); 622 | if (pid < 0) /* wtf? */ 623 | bb_perror_msg_and_die("vfork"+1); 624 | return pid; 625 | } 626 | #endif 627 | -------------------------------------------------------------------------------- /busybox/libbb/xregcomp.c: -------------------------------------------------------------------------------- 1 | /* vi: set sw=4 ts=4: */ 2 | /* 3 | * Utility routines. 4 | * 5 | * Copyright (C) many different people. 6 | * If you wrote this, please acknowledge your work. 7 | * 8 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 | */ 10 | 11 | #include "libbb.h" 12 | #include "xregex.h" 13 | 14 | char* FAST_FUNC regcomp_or_errmsg(regex_t *preg, const char *regex, int cflags) 15 | { 16 | int ret = regcomp(preg, regex, cflags); 17 | if (ret) { 18 | int errmsgsz = regerror(ret, preg, NULL, 0); 19 | char *errmsg = xmalloc(errmsgsz); 20 | regerror(ret, preg, errmsg, errmsgsz); 21 | return errmsg; 22 | } 23 | return NULL; 24 | } 25 | 26 | void FAST_FUNC xregcomp(regex_t *preg, const char *regex, int cflags) 27 | { 28 | char *errmsg = regcomp_or_errmsg(preg, regex, cflags); 29 | if (errmsg) { 30 | bb_error_msg_and_die("bad regex '%s': %s", regex, errmsg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /js_emsc/post_AWK.js: -------------------------------------------------------------------------------- 1 | /* This is the end-part of the wrapping function, defined in "pre_AWK.js" */ 2 | 3 | /* Above this point, the entire emscripten-compiled javascript generates and setups the "Module" object. 4 | All we need to do is run it */ 5 | 6 | Module['__run__'] = run; 7 | 8 | //FS.streams[3].object.printer = Module["foo_printErr"]; 9 | //Module["printErr"] = Module["foo_printErr"]; 10 | 11 | var func_run = Module['__run__']; 12 | var exit_code = func_run(); 13 | var result = {}; 14 | 15 | result['exit_code'] = exit_code; 16 | result['stderr'] = Module.awk_stderr; 17 | result['stdout'] = Module.awk_stdout; 18 | result['input'] = input_text ; 19 | result['program'] = program_source ; 20 | 21 | return result; 22 | } 23 | 24 | //NOTE: These values must match the defined enum in awk.c 25 | var NTBT_ENTER_BEGIN_BLOCK= 1; 26 | var NTBT_EXIT_BEGIN_BLOCK = 2; 27 | var NTBT_ENTER_END_BLOCK = 3; 28 | var NTBT_EXIT_END_BLOCK = 4; 29 | var NTBT_ENTER_ACTION = 5; 30 | var NTBT_EXIT_ACTION = 6; 31 | var NTBT_ENTER_PATTERN = 7; 32 | var NTBT_TAKE_PATTERN=8; //will only be called if the pattern matched 33 | var NTBT_EXIT_PATTERN=9; //will only be called if the pattern didn't match 34 | var NTBT_IMPLICIT_PATTERN = 10; // called when there's only an action, BEFORE the action notification. 35 | var NTBT_IMPLICIT_ACTION = 11; // called when there's only a pattern, AFTER the pattern notification (only if it matched). 36 | var NTBT_LAST_RULE = 12; // Last rule means no more patterns/actions - 37 | var NTBT_NEXT = 13; // 'next' called - interrupt flowcontrol 38 | var NTBT_NEXTFILE = 14; // 'nextfile' called - interrupt flowcontrol 39 | var NTBT_EXIT = 15; // 'exit' called - interrupt flowcontrol 40 | var NTBT_GETLINE = 16; // getline was explicitly or implicitly called 41 | var NTBT_END_OF_FILE = 17; //End of a single file - NOT USED 42 | var NTBT_END_OF_FILES = 18; //End of all files - finished program; moving to END block. 43 | 44 | 45 | var webawk_notification_names = {}; 46 | webawk_notification_names[NTBT_ENTER_BEGIN_BLOCK] = "BEGIN(enter)"; 47 | webawk_notification_names[NTBT_EXIT_BEGIN_BLOCK] = "BEGIN(exit)"; 48 | webawk_notification_names[NTBT_ENTER_END_BLOCK] = "END(enter)"; 49 | webawk_notification_names[NTBT_EXIT_END_BLOCK] = "END(exit)"; 50 | webawk_notification_names[NTBT_ENTER_ACTION] = "ACTION(enter)"; 51 | webawk_notification_names[NTBT_EXIT_ACTION] = "ACTION(exit)"; 52 | webawk_notification_names[NTBT_ENTER_PATTERN] = "PATTERN(enter)"; 53 | webawk_notification_names[NTBT_TAKE_PATTERN] = "PATTERN(matched)"; 54 | webawk_notification_names[NTBT_EXIT_PATTERN] = "PATTERN(no-match)" 55 | webawk_notification_names[NTBT_IMPLICIT_PATTERN] = "PATTERN(implicit)"; 56 | webawk_notification_names[NTBT_IMPLICIT_ACTION] = "ACTION(implicit)"; 57 | webawk_notification_names[NTBT_LAST_RULE] = "LAST_RULE"; 58 | webawk_notification_names[NTBT_NEXT] = "NEXT"; 59 | webawk_notification_names[NTBT_NEXTFILE] = "NEXTFILE"; 60 | webawk_notification_names[NTBT_EXIT] = "EXIT"; 61 | webawk_notification_names[NTBT_GETLINE] = "GETLINE"; 62 | webawk_notification_names[NTBT_END_OF_FILE] = "END_OF_FILE"; 63 | webawk_notification_names[NTBT_END_OF_FILES] = "END_OF_ALL_FILES"; 64 | 65 | //Define a default callback function, if needed 66 | if (typeof webawk_notification_callback == 'undefined') { 67 | console.log("Hello Developer! - I'm now defining a stub webawk_notification_callback() function."); 68 | 69 | webawk_notification_callback = function (type,start_line,start_pos,end_line,end_pos) 70 | { 71 | console.log("Webawk Notification: " + webawk_notification_names[type]); 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /js_emsc/post_AWK_web_worker.js: -------------------------------------------------------------------------------- 1 | /* This is the end-part of the wrapping function, defined in "pre_AWK.js" */ 2 | 3 | /* Above this point, the entire emscripten-compiled javascript generates and setups the "Module" object. 4 | All we need to do is run it */ 5 | 6 | Module['__run__'] = run; 7 | 8 | //FS.streams[3].object.printer = Module["foo_printErr"]; 9 | //Module["printErr"] = Module["foo_printErr"]; 10 | 11 | var func_run = Module['__run__']; 12 | var exit_code = func_run(); 13 | var result = {}; 14 | 15 | result['exit_code'] = exit_code; 16 | result['stderr'] = Module.awk_stderr; 17 | result['stdout'] = Module.awk_stdout; 18 | result['input'] = input_text ; 19 | result['program'] = program_source ; 20 | 21 | return result; 22 | } 23 | 24 | //NOTE: These values must match the defined enum in awk.c 25 | var NTBT_ENTER_BEGIN_BLOCK= 1; 26 | var NTBT_EXIT_BEGIN_BLOCK = 2; 27 | var NTBT_ENTER_END_BLOCK = 3; 28 | var NTBT_EXIT_END_BLOCK = 4; 29 | var NTBT_ENTER_ACTION = 5; 30 | var NTBT_EXIT_ACTION = 6; 31 | var NTBT_ENTER_PATTERN = 7; 32 | var NTBT_TAKE_PATTERN=8; //will only be called if the pattern matched 33 | var NTBT_EXIT_PATTERN=9; //will only be called if the pattern didn't match 34 | var NTBT_IMPLICIT_PATTERN = 10; // called when there's only an action, BEFORE the action notification. 35 | var NTBT_IMPLICIT_ACTION = 11; // called when there's only a pattern, AFTER the pattern notification (only if it matched). 36 | var NTBT_LAST_RULE = 12; // Last rule means no more patterns/actions - 37 | var NTBT_NEXT = 13; // 'next' called - interrupt flowcontrol 38 | var NTBT_NEXTFILE = 14; // 'nextfile' called - interrupt flowcontrol 39 | var NTBT_EXIT = 15; // 'exit' called - interrupt flowcontrol 40 | var NTBT_GETLINE = 16; // getline was explicitly or implicitly called 41 | var NTBT_END_OF_FILE = 17; //End of a single file - NOT USED 42 | var NTBT_END_OF_FILES = 18; //End of all files - finished program; moving to END block. 43 | 44 | 45 | var webawk_notification_names = {}; 46 | webawk_notification_names[NTBT_ENTER_BEGIN_BLOCK] = "BEGIN(enter)"; 47 | webawk_notification_names[NTBT_EXIT_BEGIN_BLOCK] = "BEGIN(exit)"; 48 | webawk_notification_names[NTBT_ENTER_END_BLOCK] = "END(enter)"; 49 | webawk_notification_names[NTBT_EXIT_END_BLOCK] = "END(exit)"; 50 | webawk_notification_names[NTBT_ENTER_ACTION] = "ACTION(enter)"; 51 | webawk_notification_names[NTBT_EXIT_ACTION] = "ACTION(exit)"; 52 | webawk_notification_names[NTBT_ENTER_PATTERN] = "PATTERN(enter)"; 53 | webawk_notification_names[NTBT_TAKE_PATTERN] = "PATTERN(matched)"; 54 | webawk_notification_names[NTBT_EXIT_PATTERN] = "PATTERN(no-match)" 55 | webawk_notification_names[NTBT_IMPLICIT_PATTERN] = "PATTERN(implicit)"; 56 | webawk_notification_names[NTBT_IMPLICIT_ACTION] = "ACTION(implicit)"; 57 | webawk_notification_names[NTBT_LAST_RULE] = "LAST_RULE"; 58 | webawk_notification_names[NTBT_NEXT] = "NEXT"; 59 | webawk_notification_names[NTBT_NEXTFILE] = "NEXTFILE"; 60 | webawk_notification_names[NTBT_EXIT] = "EXIT"; 61 | webawk_notification_names[NTBT_GETLINE] = "GETLINE"; 62 | webawk_notification_names[NTBT_END_OF_FILE] = "END_OF_FILE"; 63 | webawk_notification_names[NTBT_END_OF_FILES] = "END_OF_ALL_FILES"; 64 | 65 | //busy-wait loop sleep is an ugly hack, but we're in a web-worker. 66 | function pausecomp(millis) { 67 | var date = new Date(); 68 | var curDate = null; 69 | 70 | do { curDate = new Date(); } 71 | while(curDate-date < millis); 72 | } 73 | 74 | function webawk_notification_callback (type,start_line,start_pos,end_line,end_pos) 75 | { 76 | self.postMessage({ 77 | 'event' : 'notification', 78 | 'type' : type, 79 | 'type_name' : webawk_notification_names[type], 80 | 'start_line' : start_line, 81 | 'start_pos' : start_pos, 82 | 'end_line' : end_line, 83 | 'end_pos' : end_pos 84 | }); 85 | 86 | pausecomp(2000); 87 | } 88 | 89 | //This is a Web-Worker 90 | self.onmessage = function(event) { 91 | switch(event.data.type) 92 | { 93 | case "run_awk": 94 | var awk_program = event.data.awk_program; 95 | var input_data = event.data.input_data; 96 | 97 | var awk_result = run_web_awk(awk_program, input_data); 98 | var exit_code = awk_result.exit_code ; 99 | 100 | self.postMessage({ 101 | 'event': 'exit', 102 | 'exit_code': exit_code 103 | }); 104 | break; 105 | } 106 | }; 107 | -------------------------------------------------------------------------------- /js_emsc/pre_AWK.js: -------------------------------------------------------------------------------- 1 | 2 | /* Until a better solution comes along for running emscripten Module multiple time, we'll create it from scratch every run. 3 | Based on pre/post scripts of 'https://github.com/mdaines/viz.js' 4 | */ 5 | 6 | run_web_awk = function(program_source, input_text) 7 | { 8 | var Module = { 9 | "noInitialRun": true, 10 | 11 | arguments: [ "-f", "/my_program.awk", "/my_input.txt"], 12 | 13 | reset_outputs: function() { 14 | Module.awk_stdout = "" ; 15 | Module.awk_stderr = "" ; 16 | }, 17 | "preRun": function() { 18 | FS.createDataFile('/', 'my_program.awk', program_source, true, false); 19 | FS.createDataFile('/', 'my_input.txt', input_text, true, false); 20 | }, 21 | "print": function(text) { 22 | Module.awk_stdout += text + "\n" ; 23 | //console.log("current stdout = " + Module.awk_stdout); 24 | }, 25 | "printErr" : function(text) { 26 | console.log(text); 27 | Module.awk_stderr += text + "\n"; 28 | }, 29 | }; 30 | //Module["printErr"] = Module["foo_printErr"]; 31 | 32 | Module.reset_outputs(); 33 | 34 | /* Now comes the emscripten-generated Javascript block ... */ 35 | 36 | /* The end of this function is in "post_AWK.js" */ 37 | -------------------------------------------------------------------------------- /js_emsc/pre_AWK_web_worker.js: -------------------------------------------------------------------------------- 1 | 2 | /* Until a better solution comes along for running emscripten Module multiple time, we'll create it from scratch every run. 3 | Based on pre/post scripts of 'https://github.com/mdaines/viz.js' 4 | */ 5 | 6 | //This is the PRE emscripten scipt, 7 | //suitable for running AWK as a web-worker. 8 | 9 | run_web_awk = function(program_source, input_text) 10 | { 11 | var Module = { 12 | "noInitialRun": true, 13 | 14 | arguments: [ "-f", "/my_program.awk", "/my_input.txt"], 15 | 16 | reset_outputs: function() { 17 | Module.awk_stdout = "" ; 18 | Module.awk_stderr = "" ; 19 | }, 20 | "preRun": function() { 21 | FS.createDataFile('/', 'my_program.awk', program_source, true, false); 22 | FS.createDataFile('/', 'my_input.txt', input_text, true, false); 23 | }, 24 | "print": function(text) { 25 | self.postMessage({ 26 | 'event': 'stdout', 27 | 'stdout_text': text + "\n", 28 | }); 29 | }, 30 | }; 31 | //Module["printErr"] = Module["foo_printErr"]; 32 | 33 | Module.reset_outputs(); 34 | 35 | /* Now comes the emscripten-generated Javascript block ... */ 36 | 37 | /* The end of this function is in "post_AWK.js" */ 38 | -------------------------------------------------------------------------------- /newlib/libc/posix/cclass.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)cclass.h 8.3 (Berkeley) 3/20/94 38 | * $FreeBSD: src/lib/libc/regex/cclass.h,v 1.4 2002/03/22 23:41:56 obrien Exp $ 39 | */ 40 | 41 | 42 | typedef enum {CALNUM, CALPHA, CBLANK, CCNTRL, CDIGIT, CGRAPH, 43 | CLOWER, CPRINT, CPUNCT, CSPACE, CUPPER, CXDIGIT} citype; 44 | 45 | /* character-class table */ 46 | static struct cclass { 47 | char *name; 48 | citype fidx; 49 | } cclasses[] = { 50 | {"alnum", CALNUM}, 51 | {"alpha", CALPHA}, 52 | {"blank", CBLANK}, 53 | {"cntrl", CCNTRL}, 54 | {"digit", CDIGIT}, 55 | {"graph", CGRAPH}, 56 | {"lower", CLOWER}, 57 | {"print", CPRINT}, 58 | {"punct", CPUNCT}, 59 | {"space", CSPACE}, 60 | {"upper", CUPPER}, 61 | {"xdigit", CXDIGIT}, 62 | {NULL, } 63 | }; 64 | -------------------------------------------------------------------------------- /newlib/libc/posix/cname.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)cname.h 8.3 (Berkeley) 3/20/94 38 | * $FreeBSD: src/lib/libc/regex/cname.h,v 1.3 2002/03/22 23:41:56 obrien Exp $ 39 | */ 40 | 41 | /* character-name table */ 42 | static struct cname { 43 | char *name; 44 | char code; 45 | } cnames[] = { 46 | {"NUL", '\0'}, 47 | {"SOH", '\001'}, 48 | {"STX", '\002'}, 49 | {"ETX", '\003'}, 50 | {"EOT", '\004'}, 51 | {"ENQ", '\005'}, 52 | {"ACK", '\006'}, 53 | {"BEL", '\007'}, 54 | {"alert", '\007'}, 55 | {"BS", '\010'}, 56 | {"backspace", '\b'}, 57 | {"HT", '\011'}, 58 | {"tab", '\t'}, 59 | {"LF", '\012'}, 60 | {"newline", '\n'}, 61 | {"VT", '\013'}, 62 | {"vertical-tab", '\v'}, 63 | {"FF", '\014'}, 64 | {"form-feed", '\f'}, 65 | {"CR", '\015'}, 66 | {"carriage-return", '\r'}, 67 | {"SO", '\016'}, 68 | {"SI", '\017'}, 69 | {"DLE", '\020'}, 70 | {"DC1", '\021'}, 71 | {"DC2", '\022'}, 72 | {"DC3", '\023'}, 73 | {"DC4", '\024'}, 74 | {"NAK", '\025'}, 75 | {"SYN", '\026'}, 76 | {"ETB", '\027'}, 77 | {"CAN", '\030'}, 78 | {"EM", '\031'}, 79 | {"SUB", '\032'}, 80 | {"ESC", '\033'}, 81 | {"IS4", '\034'}, 82 | {"FS", '\034'}, 83 | {"IS3", '\035'}, 84 | {"GS", '\035'}, 85 | {"IS2", '\036'}, 86 | {"RS", '\036'}, 87 | {"IS1", '\037'}, 88 | {"US", '\037'}, 89 | {"space", ' '}, 90 | {"exclamation-mark", '!'}, 91 | {"quotation-mark", '"'}, 92 | {"number-sign", '#'}, 93 | {"dollar-sign", '$'}, 94 | {"percent-sign", '%'}, 95 | {"ampersand", '&'}, 96 | {"apostrophe", '\''}, 97 | {"left-parenthesis", '('}, 98 | {"right-parenthesis", ')'}, 99 | {"asterisk", '*'}, 100 | {"plus-sign", '+'}, 101 | {"comma", ','}, 102 | {"hyphen", '-'}, 103 | {"hyphen-minus", '-'}, 104 | {"period", '.'}, 105 | {"full-stop", '.'}, 106 | {"slash", '/'}, 107 | {"solidus", '/'}, 108 | {"zero", '0'}, 109 | {"one", '1'}, 110 | {"two", '2'}, 111 | {"three", '3'}, 112 | {"four", '4'}, 113 | {"five", '5'}, 114 | {"six", '6'}, 115 | {"seven", '7'}, 116 | {"eight", '8'}, 117 | {"nine", '9'}, 118 | {"colon", ':'}, 119 | {"semicolon", ';'}, 120 | {"less-than-sign", '<'}, 121 | {"equals-sign", '='}, 122 | {"greater-than-sign", '>'}, 123 | {"question-mark", '?'}, 124 | {"commercial-at", '@'}, 125 | {"left-square-bracket", '['}, 126 | {"backslash", '\\'}, 127 | {"reverse-solidus", '\\'}, 128 | {"right-square-bracket",']'}, 129 | {"circumflex", '^'}, 130 | {"circumflex-accent", '^'}, 131 | {"underscore", '_'}, 132 | {"low-line", '_'}, 133 | {"grave-accent", '`'}, 134 | {"left-brace", '{'}, 135 | {"left-curly-bracket", '{'}, 136 | {"vertical-line", '|'}, 137 | {"right-brace", '}'}, 138 | {"right-curly-bracket", '}'}, 139 | {"tilde", '~'}, 140 | {"DEL", '\177'}, 141 | {NULL, 0} 142 | }; 143 | -------------------------------------------------------------------------------- /newlib/libc/posix/collate.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1995 Alex Tatmanjants 3 | * at Electronni Visti IA, Kiev, Ukraine. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | 30 | #include "namespace.h" 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | //#include 38 | #include "un-namespace.h" 39 | 40 | #define reallocf realloc 41 | 42 | #include "collate.h" 43 | 44 | char *_PathLocale=""; 45 | //extern char *_PathLocale; 46 | 47 | int __collate_load_error = 1; 48 | int __collate_substitute_nontrivial; 49 | char __collate_version[STR_LEN]; 50 | u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 51 | struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 52 | struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 53 | 54 | #define FREAD(a, b, c, d) \ 55 | do { \ 56 | if (fread(a, b, c, d) != c) { \ 57 | fclose(d); \ 58 | return -1; \ 59 | } \ 60 | } while(0) 61 | 62 | void __collate_err(int ex, const char *f); 63 | 64 | int 65 | __collate_load_tables(encoding) 66 | char *encoding; 67 | { 68 | char buf[PATH_MAX]; 69 | FILE *fp; 70 | int i, save_load_error; 71 | 72 | save_load_error = __collate_load_error; 73 | __collate_load_error = 1; 74 | if (!encoding) { 75 | __collate_load_error = save_load_error; 76 | return -1; 77 | } 78 | if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) 79 | return 0; 80 | if (!_PathLocale) { 81 | __collate_load_error = save_load_error; 82 | return -1; 83 | } 84 | /* Range checking not needed, encoding has fixed size */ 85 | (void) strcpy(buf, _PathLocale); 86 | (void) strcat(buf, "/"); 87 | (void) strcat(buf, encoding); 88 | (void) strcat(buf, "/LC_COLLATE"); 89 | if ((fp = fopen(buf, "r")) == NULL) { 90 | __collate_load_error = save_load_error; 91 | return -1; 92 | } 93 | FREAD(__collate_version, sizeof(__collate_version), 1, fp); 94 | if (strcmp(__collate_version, COLLATE_VERSION) != 0) { 95 | fclose(fp); 96 | return -1; 97 | } 98 | FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), 99 | 1, fp); 100 | FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, 101 | fp); 102 | FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, 103 | fp); 104 | fclose(fp); 105 | __collate_load_error = 0; 106 | 107 | __collate_substitute_nontrivial = 0; 108 | for (i = 0; i < UCHAR_MAX + 1; i++) { 109 | if (__collate_substitute_table[i][0] != i || 110 | __collate_substitute_table[i][1] != 0) { 111 | __collate_substitute_nontrivial = 1; 112 | break; 113 | } 114 | } 115 | 116 | return 0; 117 | } 118 | 119 | u_char * 120 | __collate_substitute(s) 121 | const u_char *s; 122 | { 123 | int dest_len, len, nlen; 124 | int delta = strlen(s); 125 | u_char *dest_str = NULL; 126 | 127 | if(s == NULL || *s == '\0') 128 | return __collate_strdup(""); 129 | delta += delta / 8; 130 | dest_str = malloc(dest_len = delta); 131 | if(dest_str == NULL) 132 | __collate_err(EX_OSERR, __FUNCTION__); 133 | len = 0; 134 | while(*s) { 135 | nlen = len + strlen(__collate_substitute_table[*s]); 136 | if (dest_len <= nlen) { 137 | dest_str = reallocf(dest_str, dest_len = nlen + delta); 138 | if(dest_str == NULL) 139 | __collate_err(EX_OSERR, __FUNCTION__); 140 | } 141 | strcpy(dest_str + len, __collate_substitute_table[*s++]); 142 | len = nlen; 143 | } 144 | return dest_str; 145 | } 146 | 147 | void 148 | __collate_lookup(t, len, prim, sec) 149 | const u_char *t; 150 | int *len, *prim, *sec; 151 | { 152 | struct __collate_st_chain_pri *p2; 153 | 154 | *len = 1; 155 | *prim = *sec = 0; 156 | for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) { 157 | if(strncmp(t, p2->str, strlen(p2->str)) == 0) { 158 | *len = strlen(p2->str); 159 | *prim = p2->prim; 160 | *sec = p2->sec; 161 | return; 162 | } 163 | } 164 | *prim = __collate_char_pri_table[*t].prim; 165 | *sec = __collate_char_pri_table[*t].sec; 166 | } 167 | 168 | u_char * 169 | __collate_strdup(s) 170 | u_char *s; 171 | { 172 | u_char *t = strdup(s); 173 | 174 | if (t == NULL) 175 | __collate_err(EX_OSERR, __FUNCTION__); 176 | return t; 177 | } 178 | 179 | void 180 | __collate_err(int ex, const char *f) 181 | { 182 | const char *s; 183 | int serrno = errno; 184 | int dummy; 185 | 186 | /* Be careful to change write counts if you change the strings */ 187 | write(STDERR_FILENO, "collate_error: ", 15); 188 | write(STDERR_FILENO, f, strlen(f)); 189 | write(STDERR_FILENO, ": ", 2); 190 | //s = _strerror_r(_REENT, serrno, 1, &dummy); 191 | s = strerror(serrno); 192 | write(STDERR_FILENO, s, strlen(s)); 193 | write(STDERR_FILENO, "\n", 1); 194 | exit(ex); 195 | } 196 | 197 | #ifdef COLLATE_DEBUG 198 | void 199 | __collate_print_tables() 200 | { 201 | int i; 202 | struct __collate_st_chain_pri *p2; 203 | 204 | printf("Substitute table:\n"); 205 | for (i = 0; i < UCHAR_MAX + 1; i++) 206 | if (i != *__collate_substitute_table[i]) 207 | printf("\t'%c' --> \"%s\"\n", i, 208 | __collate_substitute_table[i]); 209 | printf("Chain priority table:\n"); 210 | for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) 211 | printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); 212 | printf("Char priority table:\n"); 213 | for (i = 0; i < UCHAR_MAX + 1; i++) 214 | printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, 215 | __collate_char_pri_table[i].sec); 216 | } 217 | #endif 218 | -------------------------------------------------------------------------------- /newlib/libc/posix/collate.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1995 Alex Tatmanjants 3 | * at Electronni Visti IA, Kiev, Ukraine. 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 2. Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 16 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 | * SUCH DAMAGE. 26 | * 27 | * $FreeBSD: src/lib/libc/locale/collate.h,v 1.11 2002/03/21 22:46:54 obrien Exp $ 28 | */ 29 | 30 | #ifndef _COLLATE_H_ 31 | #define _COLLATE_H_ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #define STR_LEN 10 38 | #define TABLE_SIZE 100 39 | #define COLLATE_VERSION "1.0\n" 40 | 41 | struct __collate_st_char_pri { 42 | int prim, sec; 43 | }; 44 | struct __collate_st_chain_pri { 45 | u_char str[STR_LEN]; 46 | int prim, sec; 47 | }; 48 | 49 | extern int __collate_load_error; 50 | extern int __collate_substitute_nontrivial; 51 | extern char __collate_version[STR_LEN]; 52 | extern u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; 53 | extern struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; 54 | extern struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; 55 | 56 | __BEGIN_DECLS 57 | u_char *__collate_strdup(u_char *); 58 | u_char *__collate_substitute(const u_char *); 59 | int __collate_load_tables(char *); 60 | void __collate_lookup(const u_char *, int *, int *, int *); 61 | int __collate_range_cmp(int, int); 62 | #ifdef COLLATE_DEBUG 63 | void __collate_print_tables(void); 64 | #endif 65 | __END_DECLS 66 | 67 | #ifndef EX_OSERR 68 | #define EX_OSERR EXIT_FAILURE 69 | #endif 70 | 71 | #endif /* !_COLLATE_H_ */ 72 | -------------------------------------------------------------------------------- /newlib/libc/posix/collcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #define ASCII_COMPATIBLE_COLLATE /* see share/colldef */ 30 | 31 | #include 32 | #include "collate.h" 33 | #ifndef ASCII_COMPATIBLE_COLLATE 34 | #include 35 | #endif 36 | 37 | /* 38 | * Compare two characters converting collate information 39 | * into ASCII-compatible range, it allows to handle 40 | * "[a-z]"-type ranges with national characters. 41 | */ 42 | 43 | int __collate_range_cmp (c1, c2) 44 | int c1, c2; 45 | { 46 | static char s1[2], s2[2]; 47 | int ret; 48 | #ifndef ASCII_COMPATIBLE_COLLATE 49 | int as1, as2, al1, al2; 50 | #endif 51 | 52 | c1 &= UCHAR_MAX; 53 | c2 &= UCHAR_MAX; 54 | if (c1 == c2) 55 | return (0); 56 | 57 | #ifndef ASCII_COMPATIBLE_COLLATE 58 | as1 = isascii(c1); 59 | as2 = isascii(c2); 60 | al1 = isalpha(c1); 61 | al2 = isalpha(c2); 62 | 63 | if (as1 || as2 || al1 || al2) { 64 | if ((as1 && as2) || (!al1 && !al2)) 65 | return (c1 - c2); 66 | if (al1 && !al2) { 67 | if (isupper(c1)) 68 | return ('A' - c2); 69 | else 70 | return ('a' - c2); 71 | } else if (al2 && !al1) { 72 | if (isupper(c2)) 73 | return (c1 - 'A'); 74 | else 75 | return (c1 - 'a'); 76 | } 77 | } 78 | #endif 79 | s1[0] = c1; 80 | s2[0] = c2; 81 | if ((ret = strcoll(s1, s2)) != 0) 82 | return (ret); 83 | return (c1 - c2); 84 | } 85 | -------------------------------------------------------------------------------- /newlib/libc/posix/namespace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001 Daniel Eischen . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * $FreeBSD: src/lib/libc/include/namespace.h,v 1.9 2002/03/29 22:43:42 markm Exp $ 27 | */ 28 | 29 | #ifndef _NAMESPACE_H_ 30 | #define _NAMESPACE_H_ 31 | 32 | /* 33 | * Adjust names so that headers declare "hidden" names. 34 | */ 35 | 36 | /* 37 | * ISO C (C90) section. Most names in libc aren't in ISO C, so they 38 | * should be here. Most aren't here... 39 | */ 40 | #define err _err 41 | #define warn _warn 42 | 43 | /* 44 | * Prototypes for syscalls/functions that need to be overridden 45 | * in libc_r/libpthread. 46 | */ 47 | #define accept _accept 48 | #define __acl_aclcheck_fd ___acl_aclcheck_fd 49 | #define __acl_delete_fd ___acl_delete_fd 50 | #define __acl_get_fd ___acl_get_fd 51 | #define __acl_set_fd ___acl_set_fd 52 | #define bind _bind 53 | #define __cap_get_fd ___cap_get_fd 54 | #define __cap_set_fd ___cap_set_fd 55 | #define close _close 56 | #define connect _connect 57 | #define dup _dup 58 | #define dup2 _dup2 59 | #define execve _execve 60 | #define fcntl _fcntl 61 | /*#define flock _flock */ 62 | #define fstat _fstat 63 | #define fstatfs _fstatfs 64 | #define fsync _fsync 65 | #define getdirentries _getdirentries 66 | #define getlogin _getlogin 67 | #define getpeername _getpeername 68 | #define getprogname _getprogname 69 | #define getsockname _getsockname 70 | #define getsockopt _getsockopt 71 | #define ioctl _ioctl 72 | /* #define kevent _kevent */ 73 | #define listen _listen 74 | #define nanosleep _nanosleep 75 | #define open _open 76 | #define poll _poll 77 | #define pthread_cond_signal _pthread_cond_signal 78 | #define pthread_cond_wait _pthread_cond_wait 79 | #define pthread_cond_init _pthread_cond_init 80 | #define pthread_exit _pthread_exit 81 | #define pthread_getspecific _pthread_getspecific 82 | #define pthread_key_create _pthread_key_create 83 | #define pthread_key_delete _pthread_key_delete 84 | #define pthread_main_np _pthread_main_np 85 | #define pthread_mutex_destroy _pthread_mutex_destroy 86 | #define pthread_mutex_init _pthread_mutex_init 87 | #define pthread_mutex_lock _pthread_mutex_lock 88 | #define pthread_mutex_trylock _pthread_mutex_trylock 89 | #define pthread_mutex_unlock _pthread_mutex_unlock 90 | #define pthread_mutexattr_init _pthread_mutexattr_init 91 | #define pthread_mutexattr_destroy _pthread_mutexattr_destroy 92 | #define pthread_mutexattr_settype _pthread_mutexattr_settype 93 | #define pthread_once _pthread_once 94 | #define pthread_rwlock_init _pthread_rwlock_init 95 | #define pthread_rwlock_rdlock _pthread_rwlock_rdlock 96 | #define pthread_rwlock_wrlock _pthread_rwlock_wrlock 97 | #define pthread_rwlock_unlock _pthread_rwlock_unlock 98 | #define pthread_self _pthread_self 99 | #define pthread_setspecific _pthread_setspecific 100 | #define pthread_sigmask _pthread_sigmask 101 | #define read _read 102 | #define readv _readv 103 | #define recvfrom _recvfrom 104 | #define recvmsg _recvmsg 105 | #define select _select 106 | #define sendmsg _sendmsg 107 | #define sendto _sendto 108 | #define setsockopt _setsockopt 109 | /*#define sigaction _sigaction*/ 110 | #define sigprocmask _sigprocmask 111 | #define sigsuspend _sigsuspend 112 | #define socket _socket 113 | #define socketpair _socketpair 114 | #define wait4 _wait4 115 | /*#define write _write*/ 116 | #define writev _writev 117 | 118 | 119 | /* 120 | * Other hidden syscalls/functions that libc_r needs to override 121 | * but are not used internally by libc. 122 | * 123 | * XXX - When modifying libc to use one of the following, remove 124 | * the prototype from below and place it in the list above. 125 | */ 126 | #if 0 127 | #define creat _creat 128 | #define fchflags _fchflags 129 | #define fchmod _fchmod 130 | #define fpathconf _fpathconf 131 | #define msync _msync 132 | #define nfssvc _nfssvc 133 | #define pause _pause 134 | #define pthread_rwlock_destroy _pthread_rwlock_destroy 135 | #define pthread_rwlock_tryrdlock _pthread_rwlock_tryrdlock 136 | #define pthread_rwlock_trywrlock _pthread_rwlock_trywrlock 137 | #define pthread_rwlockattr_init _pthread_rwlockattr_init 138 | #define pthread_rwlockattr_destroy _pthread_rwlockattr_destroy 139 | #define sched_yield _sched_yield 140 | #define sendfile _sendfile 141 | #define shutdown _shutdown 142 | #define sigaltstack _sigaltstack 143 | #define sigpending _sigpending 144 | #define sigreturn _sigreturn 145 | #define sigsetmask _sigsetmask 146 | #define sleep _sleep 147 | #define system _system 148 | #define tcdrain _tcdrain 149 | #define wait _wait 150 | #define waitpid _waitpid 151 | #endif 152 | 153 | #endif /* _NAMESPACE_H_ */ 154 | -------------------------------------------------------------------------------- /newlib/libc/posix/regerror.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | * 33 | * @(#)regerror.c 8.4 (Berkeley) 3/20/94 34 | */ 35 | 36 | #ifndef _NO_REGEX 37 | 38 | #if defined(LIBC_SCCS) && !defined(lint) 39 | static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94"; 40 | #endif /* LIBC_SCCS and not lint */ 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include "regex.h" 49 | 50 | #include "utils.h" 51 | 52 | /* ========= begin header generated by ./mkh ========= */ 53 | #ifdef __cplusplus 54 | extern "C" { 55 | #endif 56 | 57 | /* === regerror.c === */ 58 | static char *regatoi(const regex_t *preg, char *localbuf); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | /* ========= end header generated by ./mkh ========= */ 64 | /* 65 | = #define REG_NOMATCH 1 66 | = #define REG_BADPAT 2 67 | = #define REG_ECOLLATE 3 68 | = #define REG_ECTYPE 4 69 | = #define REG_EESCAPE 5 70 | = #define REG_ESUBREG 6 71 | = #define REG_EBRACK 7 72 | = #define REG_EPAREN 8 73 | = #define REG_EBRACE 9 74 | = #define REG_BADBR 10 75 | = #define REG_ERANGE 11 76 | = #define REG_ESPACE 12 77 | = #define REG_BADRPT 13 78 | = #define REG_EMPTY 14 79 | = #define REG_ASSERT 15 80 | = #define REG_INVARG 16 81 | = #define REG_ATOI 255 // convert name to number (!) 82 | = #define REG_ITOA 0400 // convert number to name (!) 83 | */ 84 | static struct rerr { 85 | int code; 86 | char *name; 87 | char *explain; 88 | } rerrs[] = { 89 | {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"}, 90 | {REG_BADPAT, "REG_BADPAT", "invalid regular expression"}, 91 | {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"}, 92 | {REG_ECTYPE, "REG_ECTYPE", "invalid character class"}, 93 | {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"}, 94 | {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"}, 95 | {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"}, 96 | {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"}, 97 | {REG_EBRACE, "REG_EBRACE", "braces not balanced"}, 98 | {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"}, 99 | {REG_ERANGE, "REG_ERANGE", "invalid character range"}, 100 | {REG_ESPACE, "REG_ESPACE", "out of memory"}, 101 | {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"}, 102 | {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"}, 103 | {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"}, 104 | {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"}, 105 | {0, "", "*** unknown regexp error code ***"} 106 | }; 107 | 108 | /* 109 | - regerror - the interface to error numbers 110 | = extern size_t regerror(int, const regex_t *, char *, size_t); 111 | */ 112 | /* ARGSUSED */ 113 | size_t 114 | regerror(errcode, preg, errbuf, errbuf_size) 115 | int errcode; 116 | const regex_t *preg; 117 | char *errbuf; 118 | size_t errbuf_size; 119 | { 120 | struct rerr *r; 121 | size_t len; 122 | int target = errcode &~ REG_ITOA; 123 | char *s; 124 | char convbuf[50]; 125 | 126 | if (errcode == REG_ATOI) 127 | s = regatoi(preg, convbuf); 128 | else { 129 | for (r = rerrs; r->code != 0; r++) 130 | if (r->code == target) 131 | break; 132 | 133 | if (errcode®_ITOA) { 134 | if (r->code != 0) 135 | (void) strcpy(convbuf, r->name); 136 | else 137 | sprintf(convbuf, "REG_0x%x", target); 138 | assert(strlen(convbuf) < sizeof(convbuf)); 139 | s = convbuf; 140 | } else 141 | s = r->explain; 142 | } 143 | 144 | len = strlen(s) + 1; 145 | if (errbuf_size > 0) { 146 | if (errbuf_size > len) 147 | (void) strcpy(errbuf, s); 148 | else { 149 | (void) strncpy(errbuf, s, errbuf_size-1); 150 | errbuf[errbuf_size-1] = '\0'; 151 | } 152 | } 153 | 154 | return(len); 155 | } 156 | 157 | /* 158 | - regatoi - internal routine to implement REG_ATOI 159 | == static char *regatoi(const regex_t *preg, char *localbuf); 160 | */ 161 | static char * 162 | regatoi(preg, localbuf) 163 | const regex_t *preg; 164 | char *localbuf; 165 | { 166 | struct rerr *r; 167 | 168 | for (r = rerrs; r->code != 0; r++) 169 | if (strcmp(r->name, preg->re_endp) == 0) 170 | break; 171 | if (r->code == 0) 172 | return("0"); 173 | 174 | sprintf(localbuf, "%d", r->code); 175 | return(localbuf); 176 | } 177 | #endif /* !_NO_REGEX */ 178 | -------------------------------------------------------------------------------- /newlib/libc/posix/regex.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992 Henry Spencer. 3 | * Copyright (c) 1992, 1993 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer of the University of Toronto. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | * 33 | * @(#)regex.h 8.2 (Berkeley) 1/3/94 34 | * $FreeBSD: src/include/regex.h,v 1.4 2002/03/23 17:24:53 imp Exp $ 35 | */ 36 | 37 | #ifndef _REGEX_H_ 38 | #define _REGEX_H_ 39 | 40 | #include 41 | 42 | //agn 43 | #define reallocf realloc 44 | 45 | /* types */ 46 | typedef off_t regoff_t; 47 | 48 | typedef struct { 49 | int re_magic; 50 | size_t re_nsub; /* number of parenthesized subexpressions */ 51 | __const char *re_endp; /* end pointer for REG_PEND */ 52 | struct re_guts *re_g; /* none of your business :-) */ 53 | } regex_t; 54 | 55 | typedef struct { 56 | regoff_t rm_so; /* start of match */ 57 | regoff_t rm_eo; /* end of match */ 58 | } regmatch_t; 59 | 60 | /* regcomp() flags */ 61 | #define REG_BASIC 0000 62 | #define REG_EXTENDED 0001 63 | #define REG_ICASE 0002 64 | #define REG_NOSUB 0004 65 | #define REG_NEWLINE 0010 66 | #define REG_NOSPEC 0020 67 | #define REG_PEND 0040 68 | #define REG_DUMP 0200 69 | 70 | /* regerror() flags */ 71 | #define REG_NOMATCH 1 72 | #define REG_BADPAT 2 73 | #define REG_ECOLLATE 3 74 | #define REG_ECTYPE 4 75 | #define REG_EESCAPE 5 76 | #define REG_ESUBREG 6 77 | #define REG_EBRACK 7 78 | #define REG_EPAREN 8 79 | #define REG_EBRACE 9 80 | #define REG_BADBR 10 81 | #define REG_ERANGE 11 82 | #define REG_ESPACE 12 83 | #define REG_BADRPT 13 84 | #define REG_EMPTY 14 85 | #define REG_ASSERT 15 86 | #define REG_INVARG 16 87 | #define REG_ATOI 255 /* convert name to number (!) */ 88 | #define REG_ITOA 0400 /* convert number to name (!) */ 89 | 90 | /* regexec() flags */ 91 | #define REG_NOTBOL 00001 92 | #define REG_NOTEOL 00002 93 | #define REG_STARTEND 00004 94 | #define REG_TRACE 00400 /* tracing of execution */ 95 | #define REG_LARGE 01000 /* force large representation */ 96 | #define REG_BACKR 02000 /* force use of backref code */ 97 | 98 | __BEGIN_DECLS 99 | int regcomp(regex_t *, const char *, int); 100 | size_t regerror(int, const regex_t *, char *, size_t); 101 | int regexec(const regex_t *, const char *, size_t, regmatch_t [], int); 102 | void regfree(regex_t *); 103 | __END_DECLS 104 | 105 | #endif /* !_REGEX_H_ */ 106 | -------------------------------------------------------------------------------- /newlib/libc/posix/regex2.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regex2.h 8.4 (Berkeley) 3/20/94 38 | * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.6 2002/03/22 23:41:56 obrien Exp $ 39 | */ 40 | 41 | /* 42 | * First, the stuff that ends up in the outside-world include file 43 | = typedef off_t regoff_t; 44 | = typedef struct { 45 | = int re_magic; 46 | = size_t re_nsub; // number of parenthesized subexpressions 47 | = const char *re_endp; // end pointer for REG_PEND 48 | = struct re_guts *re_g; // none of your business :-) 49 | = } regex_t; 50 | = typedef struct { 51 | = regoff_t rm_so; // start of match 52 | = regoff_t rm_eo; // end of match 53 | = } regmatch_t; 54 | */ 55 | /* 56 | * internals of regex_t 57 | */ 58 | #define MAGIC1 ((('r'^0200)<<8) | 'e') 59 | 60 | /* 61 | * The internal representation is a *strip*, a sequence of 62 | * operators ending with an endmarker. (Some terminology etc. is a 63 | * historical relic of earlier versions which used multiple strips.) 64 | * Certain oddities in the representation are there to permit running 65 | * the machinery backwards; in particular, any deviation from sequential 66 | * flow must be marked at both its source and its destination. Some 67 | * fine points: 68 | * 69 | * - OPLUS_ and O_PLUS are *inside* the loop they create. 70 | * - OQUEST_ and O_QUEST are *outside* the bypass they create. 71 | * - OCH_ and O_CH are *outside* the multi-way branch they create, while 72 | * OOR1 and OOR2 are respectively the end and the beginning of one of 73 | * the branches. Note that there is an implicit OOR2 following OCH_ 74 | * and an implicit OOR1 preceding O_CH. 75 | * 76 | * In state representations, an operator's bit is on to signify a state 77 | * immediately *preceding* "execution" of that operator. 78 | */ 79 | typedef unsigned long sop; /* strip operator */ 80 | typedef long sopno; 81 | #define OPRMASK 0xf8000000L 82 | #define OPDMASK 0x07ffffffL 83 | #define OPSHIFT ((unsigned)27) 84 | #define OP(n) ((n)&OPRMASK) 85 | #define OPND(n) ((n)&OPDMASK) 86 | #define SOP(op, opnd) ((op)|(opnd)) 87 | /* operators meaning operand */ 88 | /* (back, fwd are offsets) */ 89 | #define OEND (1L< uch [csetsize] */ 124 | uch mask; /* bit within array */ 125 | short hash; /* hash code */ 126 | size_t smultis; 127 | char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ 128 | } cset; 129 | /* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ 130 | #define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (uch)(c)) 131 | #define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (uch)(c)) 132 | #define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) 133 | #define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ 134 | #define MCsub(p, cs, cp) mcsub(p, cs, cp) 135 | #define MCin(p, cs, cp) mcin(p, cs, cp) 136 | 137 | /* stuff for character categories */ 138 | typedef unsigned char cat_t; 139 | 140 | /* 141 | * main compiled-expression structure 142 | */ 143 | struct re_guts { 144 | int magic; 145 | # define MAGIC2 ((('R'^0200)<<8)|'E') 146 | sop *strip; /* malloced area for strip */ 147 | int csetsize; /* number of bits in a cset vector */ 148 | int ncsets; /* number of csets in use */ 149 | cset *sets; /* -> cset [ncsets] */ 150 | uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ 151 | int cflags; /* copy of regcomp() cflags argument */ 152 | sopno nstates; /* = number of sops */ 153 | sopno firststate; /* the initial OEND (normally 0) */ 154 | sopno laststate; /* the final OEND */ 155 | int iflags; /* internal flags */ 156 | # define USEBOL 01 /* used ^ */ 157 | # define USEEOL 02 /* used $ */ 158 | # define BAD 04 /* something wrong */ 159 | int nbol; /* number of ^ used */ 160 | int neol; /* number of $ used */ 161 | int ncategories; /* how many character categories */ 162 | cat_t *categories; /* ->catspace[-CHAR_MIN] */ 163 | char *must; /* match must contain this string */ 164 | int moffset; /* latest point at which must may be located */ 165 | int *charjump; /* Boyer-Moore char jump table */ 166 | int *matchjump; /* Boyer-Moore match jump table */ 167 | int mlen; /* length of must */ 168 | size_t nsub; /* copy of re_nsub */ 169 | int backrefs; /* does it use back references? */ 170 | sopno nplus; /* how deep does it nest +s? */ 171 | /* catspace must be last */ 172 | cat_t catspace[1]; /* actually [NC] */ 173 | }; 174 | 175 | /* misc utilities */ 176 | #define OUT (CHAR_MAX+1) /* a non-character value */ 177 | #define ISWORD(c) (isalnum((uch)(c)) || (c) == '_') 178 | -------------------------------------------------------------------------------- /newlib/libc/posix/regexec.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | * 33 | * @(#)regexec.c 8.3 (Berkeley) 3/20/94 34 | */ 35 | 36 | #ifndef _NO_REGEX 37 | 38 | #if defined(LIBC_SCCS) && !defined(lint) 39 | static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94"; 40 | #endif /* LIBC_SCCS and not lint */ 41 | #include 42 | 43 | /* 44 | * the outer shell of regexec() 45 | * 46 | * This file includes engine.c *twice*, after muchos fiddling with the 47 | * macros that code uses. This lets the same code operate on two different 48 | * representations for state sets. 49 | */ 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include "regex.h" 57 | 58 | #include "utils.h" 59 | #include "regex2.h" 60 | 61 | #ifndef NDEBUG 62 | static int nope = 0; /* for use in asserts; shuts lint up */ 63 | #endif 64 | 65 | /* macros for manipulating states, small version */ 66 | #define states long 67 | #define states1 states /* for later use in regexec() decision */ 68 | #define CLEAR(v) ((v) = 0) 69 | #define SET0(v, n) ((v) &= ~((unsigned long)1 << (n))) 70 | #define SET1(v, n) ((v) |= (unsigned long)1 << (n)) 71 | #define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0) 72 | #define ASSIGN(d, s) ((d) = (s)) 73 | #define EQ(a, b) ((a) == (b)) 74 | #define STATEVARS long dummy /* dummy version */ 75 | #define STATESETUP(m, n) /* nothing */ 76 | #define STATETEARDOWN(m) /* nothing */ 77 | #define SETUP(v) ((v) = 0) 78 | #define onestate long 79 | #define INIT(o, n) ((o) = (unsigned long)1 << (n)) 80 | #define INC(o) ((o) <<= 1) 81 | #define ISSTATEIN(v, o) (((v) & (o)) != 0) 82 | /* some abbreviations; note that some of these know variable names! */ 83 | /* do "if I'm here, I can also be there" etc without branches */ 84 | #define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n)) 85 | #define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n)) 86 | #define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0) 87 | /* function names */ 88 | #define SNAMES /* engine.c looks after details */ 89 | 90 | #include "engine.c" 91 | 92 | /* now undo things */ 93 | #undef states 94 | #undef CLEAR 95 | #undef SET0 96 | #undef SET1 97 | #undef ISSET 98 | #undef ASSIGN 99 | #undef EQ 100 | #undef STATEVARS 101 | #undef STATESETUP 102 | #undef STATETEARDOWN 103 | #undef SETUP 104 | #undef onestate 105 | #undef INIT 106 | #undef INC 107 | #undef ISSTATEIN 108 | #undef FWD 109 | #undef BACK 110 | #undef ISSETBACK 111 | #undef SNAMES 112 | 113 | /* macros for manipulating states, large version */ 114 | #define states char * 115 | #define CLEAR(v) memset(v, 0, m->g->nstates) 116 | #define SET0(v, n) ((v)[n] = 0) 117 | #define SET1(v, n) ((v)[n] = 1) 118 | #define ISSET(v, n) ((v)[n]) 119 | #define ASSIGN(d, s) memcpy(d, s, m->g->nstates) 120 | #define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) 121 | #define STATEVARS long vn; char *space 122 | #define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ 123 | if ((m)->space == NULL) return(REG_ESPACE); \ 124 | (m)->vn = 0; } 125 | #define STATETEARDOWN(m) { free((m)->space); } 126 | #define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) 127 | #define onestate long 128 | #define INIT(o, n) ((o) = (n)) 129 | #define INC(o) ((o)++) 130 | #define ISSTATEIN(v, o) ((v)[o]) 131 | /* some abbreviations; note that some of these know variable names! */ 132 | /* do "if I'm here, I can also be there" etc without branches */ 133 | #define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) 134 | #define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) 135 | #define ISSETBACK(v, n) ((v)[here - (n)]) 136 | /* function names */ 137 | #define LNAMES /* flag */ 138 | 139 | #include "engine.c" 140 | 141 | /* 142 | - regexec - interface for matching 143 | = extern int regexec(const regex_t *, const char *, size_t, \ 144 | = regmatch_t [], int); 145 | = #define REG_NOTBOL 00001 146 | = #define REG_NOTEOL 00002 147 | = #define REG_STARTEND 00004 148 | = #define REG_TRACE 00400 // tracing of execution 149 | = #define REG_LARGE 01000 // force large representation 150 | = #define REG_BACKR 02000 // force use of backref code 151 | * 152 | * We put this here so we can exploit knowledge of the state representation 153 | * when choosing which matcher to call. Also, by this point the matchers 154 | * have been prototyped. 155 | */ 156 | int /* 0 success, REG_NOMATCH failure */ 157 | regexec(preg, string, nmatch, pmatch, eflags) 158 | const regex_t *preg; 159 | const char *string; 160 | size_t nmatch; 161 | regmatch_t pmatch[]; 162 | int eflags; 163 | { 164 | struct re_guts *g = preg->re_g; 165 | #ifdef REDEBUG 166 | # define GOODFLAGS(f) (f) 167 | #else 168 | # define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) 169 | #endif 170 | 171 | if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) 172 | return(REG_BADPAT); 173 | assert(!(g->iflags&BAD)); 174 | if (g->iflags&BAD) /* backstop for no-debug case */ 175 | return(REG_BADPAT); 176 | eflags = GOODFLAGS(eflags); 177 | 178 | if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) 179 | return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); 180 | else 181 | return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); 182 | } 183 | 184 | #endif /* !_NO_REGEX */ 185 | -------------------------------------------------------------------------------- /newlib/libc/posix/regfree.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 4. Neither the name of the University nor the names of its contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 | * SUCH DAMAGE. 32 | * 33 | * @(#)regfree.c 8.3 (Berkeley) 3/20/94 34 | */ 35 | 36 | #ifndef _NO_REGEX 37 | 38 | #if defined(LIBC_SCCS) && !defined(lint) 39 | static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94"; 40 | #endif /* LIBC_SCCS and not lint */ 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include "regex.h" 48 | 49 | #include "utils.h" 50 | #include "regex2.h" 51 | 52 | /* 53 | - regfree - free everything 54 | = extern void regfree(regex_t *); 55 | */ 56 | void 57 | regfree(preg) 58 | regex_t *preg; 59 | { 60 | struct re_guts *g; 61 | 62 | if (preg->re_magic != MAGIC1) /* oops */ 63 | return; /* nice to complain, but hard */ 64 | 65 | g = preg->re_g; 66 | if (g == NULL || g->magic != MAGIC2) /* oops again */ 67 | return; 68 | preg->re_magic = 0; /* mark it invalid */ 69 | g->magic = 0; /* mark it invalid */ 70 | 71 | if (g->strip != NULL) 72 | free((char *)g->strip); 73 | if (g->sets != NULL) 74 | free((char *)g->sets); 75 | if (g->setbits != NULL) 76 | free((char *)g->setbits); 77 | if (g->must != NULL) 78 | free(g->must); 79 | if (g->charjump != NULL) 80 | free(&g->charjump[CHAR_MIN]); 81 | if (g->matchjump != NULL) 82 | free(g->matchjump); 83 | free((char *)g); 84 | } 85 | 86 | #endif /* !_NO_REGEX */ 87 | -------------------------------------------------------------------------------- /newlib/libc/posix/rune.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agordon/webawk/e8a41dd493469bcf984798bcd180018e89d8a38f/newlib/libc/posix/rune.h -------------------------------------------------------------------------------- /newlib/libc/posix/un-namespace.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001 Daniel Eischen . 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | * 26 | * $FreeBSD: src/lib/libc/include/un-namespace.h,v 1.7 2002/03/29 22:43:42 markm Exp $ 27 | */ 28 | 29 | #ifndef _UN_NAMESPACE_H_ 30 | #define _UN_NAMESPACE_H_ 31 | 32 | #undef accept 33 | #undef __acl_aclcheck_fd 34 | #undef __acl_delete_fd 35 | #undef __acl_get_fd 36 | #undef __acl_set_fd 37 | #undef bind 38 | #undef __cap_get_fd 39 | #undef __cap_set_fd 40 | #undef close 41 | #undef connect 42 | #undef dup 43 | #undef dup2 44 | #undef execve 45 | #undef fcntl 46 | #undef flock 47 | #undef fstat 48 | #undef fstatfs 49 | #undef fsync 50 | #undef getdirentries 51 | #undef getlogin 52 | #undef getpeername 53 | #undef getprogname 54 | #undef getsockname 55 | #undef getsockopt 56 | #undef ioctl 57 | #undef kevent 58 | #undef listen 59 | #undef nanosleep 60 | #undef open 61 | #undef pthread_getspecific 62 | #undef pthread_key_create 63 | #undef pthread_key_delete 64 | #undef pthread_mutex_destroy 65 | #undef pthread_mutex_init 66 | #undef pthread_mutex_lock 67 | #undef pthread_mutex_trylock 68 | #undef pthread_mutex_unlock 69 | #undef pthread_mutexattr_init 70 | #undef pthread_mutexattr_destroy 71 | #undef pthread_mutexattr_settype 72 | #undef pthread_once 73 | #undef pthread_self 74 | #undef pthread_setspecific 75 | #undef read 76 | #undef readv 77 | #undef recvfrom 78 | #undef recvmsg 79 | #undef select 80 | #undef sendmsg 81 | #undef sendto 82 | #undef setsockopt 83 | #undef sigaction 84 | #undef sigprocmask 85 | #undef sigsuspend 86 | #undef socket 87 | #undef socketpair 88 | #undef wait4 89 | #undef write 90 | #undef writev 91 | 92 | #if 0 93 | #undef creat 94 | #undef fchflags 95 | #undef fchmod 96 | #undef fpathconf 97 | #undef msync 98 | #undef nfssvc 99 | #undef pause 100 | #undef poll 101 | #undef pthread_rwlock_destroy 102 | #undef pthread_rwlock_init 103 | #undef pthread_rwlock_rdlock 104 | #undef pthread_rwlock_tryrdlock 105 | #undef pthread_rwlock_trywrlock 106 | #undef pthread_rwlock_unlock 107 | #undef pthread_rwlock_wrlock 108 | #undef pthread_rwlockattr_init 109 | #undef pthread_rwlockattr_destroy 110 | #undef sched_yield 111 | #undef sendfile 112 | #undef shutdown 113 | #undef sigaltstack 114 | #undef sigpending 115 | #undef sigreturn 116 | #undef sigsetmask 117 | #undef sleep 118 | #undef system 119 | #undef tcdrain 120 | #undef wait 121 | #undef waitpid 122 | #endif /* 0 */ 123 | 124 | #ifdef _SIGNAL_H_ 125 | int _sigaction(int, const struct sigaction *, struct sigaction *); 126 | #endif 127 | 128 | #ifdef _SYS_EVENT_H_ 129 | int _kevent(int, const struct kevent *, int, struct kevent *, 130 | int, const struct timespec *); 131 | #endif 132 | 133 | #ifdef _SYS_FCNTL_H_ 134 | int _flock(int, int); 135 | #endif 136 | 137 | #undef err 138 | #undef warn 139 | 140 | #endif /* _UN_NAMESPACE_H_ */ 141 | -------------------------------------------------------------------------------- /newlib/libc/posix/utils.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)utils.h 8.3 (Berkeley) 3/20/94 38 | * $FreeBSD: src/lib/libc/regex/utils.h,v 1.2 2002/03/22 23:41:56 obrien Exp $ 39 | */ 40 | 41 | /* utility definitions */ 42 | #define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ 43 | #define INFINITY (DUPMAX + 1) 44 | #define NC (CHAR_MAX - CHAR_MIN + 1) 45 | typedef unsigned char uch; 46 | 47 | /* switch off assertions (if not already off) if no REDEBUG */ 48 | #ifndef REDEBUG 49 | #ifndef NDEBUG 50 | #define NDEBUG /* no assertions please */ 51 | #endif 52 | #endif 53 | #include 54 | 55 | /* for old systems with bcopy() but no memmove() */ 56 | #ifdef USEBCOPY 57 | #define memmove(d, s, c) bcopy(s, d, c) 58 | #endif 59 | -------------------------------------------------------------------------------- /newlib/libc/stdlib/getopt.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | 3 | getopt.c - Read command line options 4 | 5 | AUTHOR: Gregory Pietsch 6 | CREATED Fri Jan 10 21:13:05 1997 7 | 8 | DESCRIPTION: 9 | 10 | The getopt() function parses the command line arguments. Its arguments argc 11 | and argv are the argument count and array as passed to the main() function 12 | on program invocation. The argument optstring is a list of available option 13 | characters. If such a character is followed by a colon (`:'), the option 14 | takes an argument, which is placed in optarg. If such a character is 15 | followed by two colons, the option takes an optional argument, which is 16 | placed in optarg. If the option does not take an argument, optarg is NULL. 17 | 18 | The external variable optind is the index of the next array element of argv 19 | to be processed; it communicates from one call to the next which element to 20 | process. 21 | 22 | The getopt_long() function works like getopt() except that it also accepts 23 | long options started by two dashes `--'. If these take values, it is either 24 | in the form 25 | 26 | --arg=value 27 | 28 | or 29 | 30 | --arg value 31 | 32 | It takes the additional arguments longopts which is a pointer to the first 33 | element of an array of type struct option. The last element of the array 34 | has to be filled with NULL for the name field. 35 | 36 | The longind pointer points to the index of the current long option relative 37 | to longopts if it is non-NULL. 38 | 39 | The getopt() function returns the option character if the option was found 40 | successfully, `:' if there was a missing parameter for one of the options, 41 | `?' for an unknown option character, and EOF for the end of the option list. 42 | 43 | The getopt_long() function's return value is described in the header file. 44 | 45 | The function getopt_long_only() is identical to getopt_long(), except that a 46 | plus sign `+' can introduce long options as well as `--'. 47 | 48 | The following describes how to deal with options that follow non-option 49 | argv-elements. 50 | 51 | If the caller did not specify anything, the default is REQUIRE_ORDER if the 52 | environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. 53 | 54 | REQUIRE_ORDER means don't recognize them as options; stop option processing 55 | when the first non-option is seen. This is what Unix does. This mode of 56 | operation is selected by either setting the environment variable 57 | POSIXLY_CORRECT, or using `+' as the first character of the optstring 58 | parameter. 59 | 60 | PERMUTE is the default. We permute the contents of ARGV as we scan, so that 61 | eventually all the non-options are at the end. This allows options to be 62 | given in any order, even with programs that were not written to expect this. 63 | 64 | RETURN_IN_ORDER is an option available to programs that were written to 65 | expect options and other argv-elements in any order and that care about the 66 | ordering of the two. We describe each non-option argv-element as if it were 67 | the argument of an option with character code 1. Using `-' as the first 68 | character of the optstring parameter selects this mode of operation. 69 | 70 | The special argument `--' forces an end of option-scanning regardless of the 71 | value of ordering. In the case of RETURN_IN_ORDER, only `--' can cause 72 | getopt() and friends to return EOF with optind != argc. 73 | 74 | COPYRIGHT NOTICE AND DISCLAIMER: 75 | 76 | Copyright (C) 1997 Gregory Pietsch 77 | 78 | This file and the accompanying getopt.h header file are hereby placed in the 79 | public domain without restrictions. Just give the author credit, don't 80 | claim you wrote it or prevent anyone else from using it. 81 | 82 | Gregory Pietsch's current e-mail address: 83 | gpietsch@comcast.net 84 | ****************************************************************************/ 85 | 86 | #ifndef HAVE_GETOPT 87 | 88 | /* include files */ 89 | #include 90 | #include 91 | #include 92 | #define __need_getopt_newlib 93 | #include "getopt.h" 94 | 95 | /* macros */ 96 | 97 | /* types */ 98 | typedef enum GETOPT_ORDERING_T 99 | { 100 | PERMUTE, 101 | RETURN_IN_ORDER, 102 | REQUIRE_ORDER 103 | } GETOPT_ORDERING_T; 104 | 105 | /* globally-defined variables */ 106 | char *optarg = 0; 107 | int optind = 0; 108 | int opterr = 1; 109 | int optopt = '?'; 110 | 111 | /* static variables */ 112 | static int optwhere = 0; 113 | 114 | /* functions */ 115 | 116 | /* reverse_argv_elements: reverses num elements starting at argv */ 117 | static void 118 | reverse_argv_elements (char **argv, int num) 119 | { 120 | int i; 121 | char *tmp; 122 | 123 | for (i = 0; i < (num >> 1); i++) 124 | { 125 | tmp = argv[i]; 126 | argv[i] = argv[num - i - 1]; 127 | argv[num - i - 1] = tmp; 128 | } 129 | } 130 | 131 | /* permute: swap two blocks of argv-elements given their lengths */ 132 | static void 133 | permute (char *const argv[], int len1, int len2) 134 | { 135 | reverse_argv_elements ((char **) argv, len1); 136 | reverse_argv_elements ((char **) argv, len1 + len2); 137 | reverse_argv_elements ((char **) argv, len2); 138 | } 139 | 140 | /* is_option: is this argv-element an option or the end of the option list? */ 141 | static int 142 | is_option (char *argv_element, int only) 143 | { 144 | return ((argv_element == 0) 145 | || (argv_element[0] == '-') || (only && argv_element[0] == '+')); 146 | } 147 | 148 | /* read_globals: read the values from the globals into a getopt_data 149 | structure */ 150 | static void 151 | read_globals (struct getopt_data *data) 152 | { 153 | data->optarg = optarg; 154 | data->optind = optind; 155 | data->opterr = opterr; 156 | data->optopt = optopt; 157 | data->optwhere = optwhere; 158 | } 159 | 160 | /* write_globals: write the values into the globals from a getopt_data 161 | structure */ 162 | static void 163 | write_globals (struct getopt_data *data) 164 | { 165 | optarg = data->optarg; 166 | optind = data->optind; 167 | opterr = data->opterr; 168 | optopt = data->optopt; 169 | optwhere = data->optwhere; 170 | } 171 | 172 | /* getopt_internal: the function that does all the dirty work */ 173 | static int 174 | getopt_internal (int argc, char *const argv[], const char *shortopts, 175 | const struct option *longopts, int *longind, int only, 176 | struct getopt_data *data) 177 | { 178 | GETOPT_ORDERING_T ordering = PERMUTE; 179 | size_t permute_from = 0; 180 | int num_nonopts = 0; 181 | int optindex = 0; 182 | size_t match_chars = 0; 183 | char *possible_arg = 0; 184 | int longopt_match = -1; 185 | int has_arg = -1; 186 | char *cp = 0; 187 | int arg_next = 0; 188 | 189 | /* first, deal with silly parameters and easy stuff */ 190 | if (argc == 0 || argv == 0 || (shortopts == 0 && longopts == 0) 191 | || data->optind >= argc || argv[data->optind] == 0) 192 | return EOF; 193 | if (strcmp (argv[data->optind], "--") == 0) 194 | { 195 | data->optind++; 196 | return EOF; 197 | } 198 | 199 | /* if this is our first time through */ 200 | if (data->optind == 0) 201 | data->optind = data->optwhere = 1; 202 | 203 | /* define ordering */ 204 | if (shortopts != 0 && (*shortopts == '-' || *shortopts == '+')) 205 | { 206 | ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER; 207 | shortopts++; 208 | } 209 | else 210 | ordering = (getenv ("POSIXLY_CORRECT") != 0) ? REQUIRE_ORDER : PERMUTE; 211 | 212 | /* 213 | * based on ordering, find our next option, if we're at the beginning of 214 | * one 215 | */ 216 | if (data->optwhere == 1) 217 | { 218 | switch (ordering) 219 | { 220 | default: /* shouldn't happen */ 221 | case PERMUTE: 222 | permute_from = data->optind; 223 | num_nonopts = 0; 224 | while (!is_option (argv[data->optind], only)) 225 | { 226 | data->optind++; 227 | num_nonopts++; 228 | } 229 | if (argv[data->optind] == 0) 230 | { 231 | /* no more options */ 232 | data->optind = permute_from; 233 | return EOF; 234 | } 235 | else if (strcmp (argv[data->optind], "--") == 0) 236 | { 237 | /* no more options, but have to get `--' out of the way */ 238 | permute (argv + permute_from, num_nonopts, 1); 239 | data->optind = permute_from + 1; 240 | return EOF; 241 | } 242 | break; 243 | case RETURN_IN_ORDER: 244 | if (!is_option (argv[data->optind], only)) 245 | { 246 | data->optarg = argv[data->optind++]; 247 | return (data->optopt = 1); 248 | } 249 | break; 250 | case REQUIRE_ORDER: 251 | if (!is_option (argv[data->optind], only)) 252 | return EOF; 253 | break; 254 | } 255 | } 256 | /* we've got an option, so parse it */ 257 | 258 | /* first, is it a long option? */ 259 | if (longopts != 0 260 | && (memcmp (argv[data->optind], "--", 2) == 0 261 | || (only && argv[data->optind][0] == '+')) && data->optwhere == 1) 262 | { 263 | /* handle long options */ 264 | if (memcmp (argv[data->optind], "--", 2) == 0) 265 | data->optwhere = 2; 266 | longopt_match = -1; 267 | possible_arg = strchr (argv[data->optind] + data->optwhere, '='); 268 | if (possible_arg == 0) 269 | { 270 | /* no =, so next argv might be arg */ 271 | match_chars = strlen (argv[data->optind]); 272 | possible_arg = argv[data->optind] + match_chars; 273 | match_chars = match_chars - data->optwhere; 274 | } 275 | else 276 | match_chars = (possible_arg - argv[data->optind]) - data->optwhere; 277 | for (optindex = 0; longopts[optindex].name != 0; ++optindex) 278 | { 279 | if (memcmp 280 | (argv[data->optind] + data->optwhere, longopts[optindex].name, 281 | match_chars) == 0) 282 | { 283 | /* do we have an exact match? */ 284 | if (match_chars == (int) (strlen (longopts[optindex].name))) 285 | { 286 | longopt_match = optindex; 287 | break; 288 | } 289 | /* do any characters match? */ 290 | else 291 | { 292 | if (longopt_match < 0) 293 | longopt_match = optindex; 294 | else 295 | { 296 | /* we have ambiguous options */ 297 | if (data->opterr) 298 | fprintf (stderr, "%s: option `%s' is ambiguous " 299 | "(could be `--%s' or `--%s')\n", 300 | argv[0], 301 | argv[data->optind], 302 | longopts[longopt_match].name, 303 | longopts[optindex].name); 304 | return (data->optopt = '?'); 305 | } 306 | } 307 | } 308 | } 309 | if (longopt_match >= 0) 310 | has_arg = longopts[longopt_match].has_arg; 311 | } 312 | 313 | /* if we didn't find a long option, is it a short option? */ 314 | if (longopt_match < 0 && shortopts != 0) 315 | { 316 | cp = strchr (shortopts, argv[data->optind][data->optwhere]); 317 | if (cp == 0) 318 | { 319 | /* couldn't find option in shortopts */ 320 | if (data->opterr) 321 | fprintf (stderr, 322 | "%s: invalid option -- `-%c'\n", 323 | argv[0], argv[data->optind][data->optwhere]); 324 | data->optwhere++; 325 | if (argv[data->optind][data->optwhere] == '\0') 326 | { 327 | data->optind++; 328 | data->optwhere = 1; 329 | } 330 | return (data->optopt = '?'); 331 | } 332 | has_arg = ((cp[1] == ':') 333 | ? ((cp[2] == ':') ? OPTIONAL_ARG : REQUIRED_ARG) : NO_ARG); 334 | possible_arg = argv[data->optind] + data->optwhere + 1; 335 | data->optopt = *cp; 336 | } 337 | 338 | /* get argument and reset data->optwhere */ 339 | arg_next = 0; 340 | switch (has_arg) 341 | { 342 | case OPTIONAL_ARG: 343 | if (*possible_arg == '=') 344 | possible_arg++; 345 | data->optarg = (*possible_arg != '\0') ? possible_arg : 0; 346 | data->optwhere = 1; 347 | break; 348 | case REQUIRED_ARG: 349 | if (*possible_arg == '=') 350 | possible_arg++; 351 | if (*possible_arg != '\0') 352 | { 353 | data->optarg = possible_arg; 354 | data->optwhere = 1; 355 | } 356 | else if (data->optind + 1 >= argc) 357 | { 358 | if (data->opterr) 359 | { 360 | fprintf (stderr, "%s: argument required for option `", argv[0]); 361 | if (longopt_match >= 0) 362 | fprintf (stderr, "--%s'\n", longopts[longopt_match].name); 363 | else 364 | fprintf (stderr, "-%c'\n", *cp); 365 | } 366 | data->optind++; 367 | return (data->optopt = ':'); 368 | } 369 | else 370 | { 371 | data->optarg = argv[data->optind + 1]; 372 | arg_next = 1; 373 | data->optwhere = 1; 374 | } 375 | break; 376 | default: /* shouldn't happen */ 377 | case NO_ARG: 378 | if (longopt_match < 0) 379 | { 380 | data->optwhere++; 381 | if (argv[data->optind][data->optwhere] == '\0') 382 | data->optwhere = 1; 383 | } 384 | else 385 | data->optwhere = 1; 386 | data->optarg = 0; 387 | break; 388 | } 389 | 390 | /* do we have to permute or otherwise modify data->optind? */ 391 | if (ordering == PERMUTE && data->optwhere == 1 && num_nonopts != 0) 392 | { 393 | permute (argv + permute_from, num_nonopts, 1 + arg_next); 394 | data->optind = permute_from + 1 + arg_next; 395 | } 396 | else if (data->optwhere == 1) 397 | data->optind = data->optind + 1 + arg_next; 398 | 399 | /* finally return */ 400 | if (longopt_match >= 0) 401 | { 402 | if (longind != 0) 403 | *longind = longopt_match; 404 | if (longopts[longopt_match].flag != 0) 405 | { 406 | *(longopts[longopt_match].flag) = longopts[longopt_match].val; 407 | return 0; 408 | } 409 | else 410 | return longopts[longopt_match].val; 411 | } 412 | else 413 | return data->optopt; 414 | } 415 | 416 | int 417 | getopt (int argc, char *const argv[], const char *optstring) 418 | { 419 | struct getopt_data data; 420 | int r; 421 | 422 | read_globals (&data); 423 | r = getopt_internal (argc, argv, optstring, 0, 0, 0, &data); 424 | write_globals (&data); 425 | return r; 426 | } 427 | 428 | int 429 | getopt_long (int argc, char *const argv[], const char *shortopts, 430 | const struct option *longopts, int *longind) 431 | { 432 | struct getopt_data data; 433 | int r; 434 | 435 | read_globals (&data); 436 | r = getopt_internal (argc, argv, shortopts, longopts, longind, 0, &data); 437 | write_globals (&data); 438 | return r; 439 | } 440 | 441 | int 442 | getopt_long_only (int argc, char *const argv[], const char *shortopts, 443 | const struct option *longopts, int *longind) 444 | { 445 | struct getopt_data data; 446 | int r; 447 | 448 | read_globals (&data); 449 | r = getopt_internal (argc, argv, shortopts, longopts, longind, 1, &data); 450 | write_globals (&data); 451 | return r; 452 | } 453 | 454 | int 455 | __getopt_r (int argc, char *const argv[], const char *optstring, 456 | struct getopt_data *data) 457 | { 458 | return getopt_internal (argc, argv, optstring, 0, 0, 0, data); 459 | } 460 | 461 | int 462 | __getopt_long_r (int argc, char *const argv[], const char *shortopts, 463 | const struct option *longopts, int *longind, 464 | struct getopt_data *data) 465 | { 466 | return getopt_internal (argc, argv, shortopts, longopts, longind, 0, data); 467 | } 468 | 469 | int 470 | __getopt_long_only_r (int argc, char *const argv[], const char *shortopts, 471 | const struct option *longopts, int *longind, 472 | struct getopt_data *data) 473 | { 474 | return getopt_internal (argc, argv, shortopts, longopts, longind, 1, data); 475 | } 476 | 477 | #endif /* !HAVE_GETOPT */ 478 | 479 | /* end of file GETOPT.C */ 480 | -------------------------------------------------------------------------------- /newlib/libc/stdlib/getopt.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | 3 | getopt.h - Read command line options 4 | 5 | AUTHOR: Gregory Pietsch 6 | CREATED Thu Jan 09 22:37:00 1997 7 | 8 | DESCRIPTION: 9 | 10 | The getopt() function parses the command line arguments. Its arguments argc 11 | and argv are the argument count and array as passed to the main() function 12 | on program invocation. The argument optstring is a list of available option 13 | characters. If such a character is followed by a colon (`:'), the option 14 | takes an argument, which is placed in optarg. If such a character is 15 | followed by two colons, the option takes an optional argument, which is 16 | placed in optarg. If the option does not take an argument, optarg is NULL. 17 | 18 | The external variable optind is the index of the next array element of argv 19 | to be processed; it communicates from one call to the next which element to 20 | process. 21 | 22 | The getopt_long() function works like getopt() except that it also accepts 23 | long options started by two dashes `--'. If these take values, it is either 24 | in the form 25 | 26 | --arg=value 27 | 28 | or 29 | 30 | --arg value 31 | 32 | It takes the additional arguments longopts which is a pointer to the first 33 | element of an array of type GETOPT_LONG_OPTION_T, defined below. The last 34 | element of the array has to be filled with NULL for the name field. 35 | 36 | The longind pointer points to the index of the current long option relative 37 | to longopts if it is non-NULL. 38 | 39 | The getopt() function returns the option character if the option was found 40 | successfully, `:' if there was a missing parameter for one of the options, 41 | `?' for an unknown option character, and EOF for the end of the option list. 42 | 43 | The getopt_long() function's return value is described below. 44 | 45 | The function getopt_long_only() is identical to getopt_long(), except that a 46 | plus sign `+' can introduce long options as well as `--'. 47 | 48 | Describe how to deal with options that follow non-option ARGV-elements. 49 | 50 | If the caller did not specify anything, the default is REQUIRE_ORDER if the 51 | environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. 52 | 53 | REQUIRE_ORDER means don't recognize them as options; stop option processing 54 | when the first non-option is seen. This is what Unix does. This mode of 55 | operation is selected by either setting the environment variable 56 | POSIXLY_CORRECT, or using `+' as the first character of the optstring 57 | parameter. 58 | 59 | PERMUTE is the default. We permute the contents of ARGV as we scan, so that 60 | eventually all the non-options are at the end. This allows options to be 61 | given in any order, even with programs that were not written to expect this. 62 | 63 | RETURN_IN_ORDER is an option available to programs that were written to 64 | expect options and other ARGV-elements in any order and that care about the 65 | ordering of the two. We describe each non-option ARGV-element as if it were 66 | the argument of an option with character code 1. Using `-' as the first 67 | character of the optstring parameter selects this mode of operation. 68 | 69 | The special argument `--' forces an end of option-scanning regardless of the 70 | value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause 71 | getopt() and friends to return EOF with optind != argc. 72 | 73 | COPYRIGHT NOTICE AND DISCLAIMER: 74 | 75 | Copyright (C) 1997 Gregory Pietsch 76 | 77 | This file and the accompanying getopt.c implementation file are hereby 78 | placed in the public domain without restrictions. Just give the author 79 | credit, don't claim you wrote it or prevent anyone else from using it. 80 | 81 | Gregory Pietsch's current e-mail address: 82 | gpietsch@comcast.net 83 | ****************************************************************************/ 84 | 85 | /* This is a glibc-extension header file. */ 86 | 87 | #ifndef GETOPT_H 88 | #define GETOPT_H 89 | 90 | // #include "_ansi.h" 91 | #ifndef _EXFUN 92 | #define _EXFUN(name, proto) name proto 93 | #endif 94 | 95 | /* include files needed by this include file */ 96 | 97 | #define no_argument 0 98 | #define required_argument 1 99 | #define optional_argument 2 100 | 101 | #ifdef __cplusplus 102 | extern "C" 103 | { 104 | 105 | #endif /* __cplusplus */ 106 | 107 | /* types defined by this include file */ 108 | struct option 109 | { 110 | char *name; /* the name of the long option */ 111 | int has_arg; /* one of the above macros */ 112 | int *flag; /* determines if getopt_long() returns a 113 | * value for a long option; if it is 114 | * non-NULL, 0 is returned as a function 115 | * value and the value of val is stored in 116 | * the area pointed to by flag. Otherwise, 117 | * val is returned. */ 118 | int val; /* determines the value to return if flag is 119 | * NULL. */ 120 | 121 | }; 122 | 123 | /* While getopt.h is a glibc extension, the following are newlib extensions. 124 | * They are optionally included via the __need_getopt_newlib flag. */ 125 | 126 | #ifdef __need_getopt_newlib 127 | 128 | /* macros defined by this include file */ 129 | #define NO_ARG no_argument 130 | #define REQUIRED_ARG required_argument 131 | #define OPTIONAL_ARG optional_argument 132 | 133 | /* The GETOPT_DATA_INITIALIZER macro is used to initialize a statically- 134 | allocated variable of type struct getopt_data. */ 135 | #define GETOPT_DATA_INITIALIZER {0,0,0,0,0} 136 | 137 | /* These #defines are to make accessing the reentrant functions easier. */ 138 | #define getopt_r __getopt_r 139 | #define getopt_long_r __getopt_long_r 140 | #define getopt_long_only_r __getopt_long_only_r 141 | 142 | /* The getopt_data structure is for reentrancy. Its members are similar to 143 | the externally-defined variables. */ 144 | typedef struct getopt_data 145 | { 146 | char *optarg; 147 | int optind, opterr, optopt, optwhere; 148 | } getopt_data; 149 | 150 | #endif /* __need_getopt_newlib */ 151 | 152 | /* externally-defined variables */ 153 | extern char *optarg; 154 | extern int optind; 155 | extern int opterr; 156 | extern int optopt; 157 | 158 | /* function prototypes */ 159 | int _EXFUN (getopt, 160 | (int __argc, char *const __argv[], const char *__optstring)); 161 | 162 | int _EXFUN (getopt_long, 163 | (int __argc, char *const __argv[], const char *__shortopts, 164 | const struct option * __longopts, int *__longind)); 165 | 166 | int _EXFUN (getopt_long_only, 167 | (int __argc, char *const __argv[], const char *__shortopts, 168 | const struct option * __longopts, int *__longind)); 169 | 170 | #ifdef __need_getopt_newlib 171 | int _EXFUN (__getopt_r, 172 | (int __argc, char *const __argv[], const char *__optstring, 173 | struct getopt_data * __data)); 174 | 175 | int _EXFUN (__getopt_long_r, 176 | (int __argc, char *const __argv[], const char *__shortopts, 177 | const struct option * __longopts, int *__longind, 178 | struct getopt_data * __data)); 179 | 180 | int _EXFUN (__getopt_long_only_r, 181 | (int __argc, char *const __argv[], const char *__shortopts, 182 | const struct option * __longopts, int *__longind, 183 | struct getopt_data * __data)); 184 | #endif /* __need_getopt_newlib */ 185 | 186 | #ifdef __cplusplus 187 | }; 188 | 189 | #endif /* __cplusplus */ 190 | 191 | #endif /* GETOPT_H */ 192 | 193 | /* END OF FILE getopt.h */ 194 | -------------------------------------------------------------------------------- /prebuilt/awk_node.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agordon/webawk/e8a41dd493469bcf984798bcd180018e89d8a38f/prebuilt/awk_node.js.gz -------------------------------------------------------------------------------- /prebuilt/awk_web.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agordon/webawk/e8a41dd493469bcf984798bcd180018e89d8a38f/prebuilt/awk_web.js.gz -------------------------------------------------------------------------------- /tests/my_input.txt: -------------------------------------------------------------------------------- 1 | 1 a 2 | 2 b 3 | 3 c 4 | 4 d 5 | -------------------------------------------------------------------------------- /tests/my_program.awk: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | print "Hello World" 3 | } 4 | 5 | $2 ~ /c/ { print $1 } 6 | -------------------------------------------------------------------------------- /tests/web_test.js: -------------------------------------------------------------------------------- 1 | /* 2 | This is a driver for testing the AWK javascript generated for the web 3 | (as opposed to the one generated for node.js) 4 | 5 | It is assumed the generated javascript is concatenated above this script, 6 | and that it exposes a single javascript function: run_web_awk(). 7 | 8 | See "make web-test" . 9 | */ 10 | 11 | var test1_program = 'BEGIN { print "Hello Busybox/AWK/Javascript World" } $$2 ~ /2/ { print $$1 }'; 12 | var test1_input = "1 A\n2 B\n3 C\n"; 13 | 14 | var r = run_web_awk(test1_program, test1_input); 15 | 16 | console.log("test1 exit code: " + r.exit_code); 17 | 18 | -------------------------------------------------------------------------------- /website/awk_web.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Emscripten-Generated Code 7 | 13 | 14 | 15 |

AWK Program

16 | 22 |

Input File

23 | 29 | 30 |
31 | 32 |

Exit code:
(not run yet)

33 | 34 |

STDOUT

35 | 37 | 38 |

STDERR

39 | 40 | 41 |
42 | 43 | 44 | 45 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /website/awk_web_worker.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WebAWK with Callbacks 7 | 8 | 9 | 10 | 12 | 14 | 15 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 |

Interactive WebAWK - AWK in Javascript

49 |

Enjoy AWK without leaving your browser.

50 |
51 |
52 | 53 | 54 |
55 | 56 |
57 |
58 | This page will demonstrate the interaction between AWK's patterns, actions, and input files.

59 | 60 | Modify the AWK program and input data as desired, then click Run.

61 | More information at WebAwk Git repository 62 |

63 |
64 | 65 |
66 |
67 |

AWK Program

68 |
BEGIN { 69 | print "Hello from Web/AWK World" 70 | } 71 | $2 ~ /C/ { print $1 * 2 } 72 | 73 | { print ( $1 + 5 ) * 1.4 } 74 | 75 | $1*10 > 23 76 | 77 |
78 |
79 | 80 |
81 |

Input File

82 |
1 A 83 | 2 B 84 | 3 C 85 | 4 D
86 |
87 |
88 | 89 |
90 |
91 | 98 |
99 |
100 | 107 |
108 |
109 | 110 | 111 |
112 |
113 |
114 | 115 | 116 |
117 |
118 | 119 |
120 |
121 | 122 | 129 | 130 |

Output

131 |

132 | 
133 | 	
134 |
135 | 136 |
137 | 138 | 326 | 327 | 328 | 329 | --------------------------------------------------------------------------------