diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-17 09:51:43 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-17 09:51:43 +0100 |
| commit | e4ba4c43716b6f550de3bf922e6f25e2dd9e983e (patch) | |
| tree | b7830b7f164002c60e867b0777e7632c0f1298e4 /miscutils | |
| parent | c5774a3458ab660e9f75526b3cd8e67da520e0ae (diff) | |
| download | busybox-w32-e4ba4c43716b6f550de3bf922e6f25e2dd9e983e.tar.gz busybox-w32-e4ba4c43716b6f550de3bf922e6f25e2dd9e983e.tar.bz2 busybox-w32-e4ba4c43716b6f550de3bf922e6f25e2dd9e983e.zip | |
bc: parse file arguments piecemeal (do not read entire file)
function old new delta
bc_read_line 336 406 +70
zbc_vm_execute_FILE - 67 +67
zbc_lex_next 2309 2318 +9
zbc_program_exec 4002 4008 +6
bc_program_index 66 64 -2
bc_vm_run 139 124 -15
zbc_vm_file 208 32 -176
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/3 up/down: 152/-193) Total: -41 bytes
text data bss dec hex filename
981736 485 7296 989517 f194d busybox_old
981667 485 7296 989448 f1908 busybox_unstripped
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'miscutils')
| -rw-r--r-- | miscutils/bc.c | 183 |
1 files changed, 78 insertions, 105 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index c92f6f813..2570e8313 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
| @@ -694,7 +694,6 @@ struct globals { | |||
| 694 | IF_FEATURE_BC_SIGNALS(smallint ttyin;) | 694 | IF_FEATURE_BC_SIGNALS(smallint ttyin;) |
| 695 | IF_FEATURE_CLEAN_UP(smallint exiting;) | 695 | IF_FEATURE_CLEAN_UP(smallint exiting;) |
| 696 | smallint in_read; | 696 | smallint in_read; |
| 697 | smallint use_stdin; | ||
| 698 | 697 | ||
| 699 | BcParse prs; | 698 | BcParse prs; |
| 700 | BcProgram prog; | 699 | BcProgram prog; |
| @@ -704,7 +703,8 @@ struct globals { | |||
| 704 | unsigned err_line; | 703 | unsigned err_line; |
| 705 | 704 | ||
| 706 | BcVec files; | 705 | BcVec files; |
| 707 | BcVec stdin_buffer; | 706 | BcVec input_buffer; |
| 707 | FILE *input_fp; | ||
| 708 | 708 | ||
| 709 | char *env_args; | 709 | char *env_args; |
| 710 | 710 | ||
| @@ -1317,8 +1317,8 @@ static int bad_input_byte(char c) | |||
| 1317 | return 0; | 1317 | return 0; |
| 1318 | } | 1318 | } |
| 1319 | 1319 | ||
| 1320 | // Note: it _appends_ data from the stdin to vec. | 1320 | // Note: it _appends_ data from fp to vec. |
| 1321 | static void bc_read_line(BcVec *vec) | 1321 | static void bc_read_line(BcVec *vec, FILE *fp) |
| 1322 | { | 1322 | { |
| 1323 | again: | 1323 | again: |
| 1324 | fflush_and_check(); | 1324 | fflush_and_check(); |
| @@ -1326,6 +1326,17 @@ static void bc_read_line(BcVec *vec) | |||
| 1326 | #if ENABLE_FEATURE_BC_SIGNALS | 1326 | #if ENABLE_FEATURE_BC_SIGNALS |
| 1327 | if (G_interrupt) { // ^C was pressed | 1327 | if (G_interrupt) { // ^C was pressed |
| 1328 | intr: | 1328 | intr: |
| 1329 | if (fp != stdin) { | ||
| 1330 | // ^C while running a script (bc SCRIPT): die. | ||
| 1331 | // We do not return to interactive prompt: | ||
| 1332 | // user might be running us from a shell, | ||
| 1333 | // and SCRIPT might be intended to terminate | ||
| 1334 | // (e.g. contain a "halt" stmt). | ||
| 1335 | // ^C dropping user into a bc prompt instead of | ||
| 1336 | // the shell would be unexpected. | ||
| 1337 | xfunc_die(); | ||
| 1338 | } | ||
| 1339 | // ^C while interactive input | ||
| 1329 | G_interrupt = 0; | 1340 | G_interrupt = 0; |
| 1330 | // GNU bc says "interrupted execution." | 1341 | // GNU bc says "interrupted execution." |
| 1331 | // GNU dc says "Interrupt!" | 1342 | // GNU dc says "Interrupt!" |
| @@ -1333,14 +1344,14 @@ static void bc_read_line(BcVec *vec) | |||
| 1333 | } | 1344 | } |
| 1334 | 1345 | ||
| 1335 | # if ENABLE_FEATURE_EDITING | 1346 | # if ENABLE_FEATURE_EDITING |
| 1336 | if (G_ttyin) { | 1347 | if (G_ttyin && fp == stdin) { |
| 1337 | int n, i; | 1348 | int n, i; |
| 1338 | # define line_buf bb_common_bufsiz1 | 1349 | # define line_buf bb_common_bufsiz1 |
| 1339 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); | 1350 | n = read_line_input(G.line_input_state, "", line_buf, COMMON_BUFSIZE); |
| 1340 | if (n <= 0) { // read errors or EOF, or ^D, or ^C | 1351 | if (n <= 0) { // read errors or EOF, or ^D, or ^C |
| 1341 | if (n == 0) // ^C | 1352 | if (n == 0) // ^C |
| 1342 | goto intr; | 1353 | goto intr; |
| 1343 | bc_vec_pushZeroByte(vec); | 1354 | bc_vec_pushZeroByte(vec); // ^D or EOF (or error) |
| 1344 | return; | 1355 | return; |
| 1345 | } | 1356 | } |
| 1346 | i = 0; | 1357 | i = 0; |
| @@ -1359,60 +1370,38 @@ static void bc_read_line(BcVec *vec) | |||
| 1359 | bool bad_chars = 0; | 1370 | bool bad_chars = 0; |
| 1360 | size_t len = vec->len; | 1371 | size_t len = vec->len; |
| 1361 | 1372 | ||
| 1362 | IF_FEATURE_BC_SIGNALS(errno = 0;) | ||
| 1363 | do { | 1373 | do { |
| 1364 | c = fgetc(stdin); | 1374 | #if ENABLE_FEATURE_BC_SIGNALS |
| 1365 | #if ENABLE_FEATURE_BC_SIGNALS && !ENABLE_FEATURE_EDITING | 1375 | if (G_interrupt) { |
| 1366 | // Both conditions appear simultaneously, check both just in case | 1376 | // ^C was pressed: ignore entire line, get another one |
| 1367 | if (errno == EINTR || G_interrupt) { | 1377 | vec->len = len; |
| 1368 | // ^C was pressed | ||
| 1369 | clearerr(stdin); | ||
| 1370 | goto intr; | 1378 | goto intr; |
| 1371 | } | 1379 | } |
| 1372 | #endif | 1380 | #endif |
| 1381 | c = fgetc(fp); | ||
| 1373 | if (c == EOF) { | 1382 | if (c == EOF) { |
| 1374 | if (ferror(stdin)) | 1383 | if (ferror(fp)) |
| 1375 | quit(); // this emits error message | 1384 | bb_perror_msg_and_die("input error"); |
| 1376 | // Note: EOF does not append '\n', therefore: | 1385 | // Note: EOF does not append '\n' |
| 1377 | // printf 'print 123\n' | bc - works | ||
| 1378 | // printf 'print 123' | bc - fails (syntax error) | ||
| 1379 | break; | 1386 | break; |
| 1380 | } | 1387 | } |
| 1381 | bad_chars |= bad_input_byte(c); | 1388 | bad_chars |= bad_input_byte(c); |
| 1382 | bc_vec_pushByte(vec, (char)c); | 1389 | bc_vec_pushByte(vec, (char)c); |
| 1383 | } while (c != '\n'); | 1390 | } while (c != '\n'); |
| 1391 | |||
| 1384 | if (bad_chars) { | 1392 | if (bad_chars) { |
| 1385 | // Bad chars on this line, ignore entire line | 1393 | // Bad chars on this line |
| 1386 | vec->len = len; | 1394 | if (!G.prog.file) { // stdin |
| 1387 | goto again; | 1395 | // ignore entire line, get another one |
| 1396 | vec->len = len; | ||
| 1397 | goto again; | ||
| 1398 | } | ||
| 1399 | bb_perror_msg_and_die("file '%s' is not text", G.prog.file); | ||
| 1388 | } | 1400 | } |
| 1389 | bc_vec_pushZeroByte(vec); | 1401 | bc_vec_pushZeroByte(vec); |
| 1390 | } | 1402 | } |
| 1391 | } | 1403 | } |
| 1392 | 1404 | ||
| 1393 | static char* bc_read_file(const char *path) | ||
| 1394 | { | ||
| 1395 | char *buf; | ||
| 1396 | size_t size = ((size_t) -1); | ||
| 1397 | size_t i; | ||
| 1398 | |||
| 1399 | // Never returns NULL (dies on errors) | ||
| 1400 | buf = xmalloc_xopen_read_close(path, &size); | ||
| 1401 | |||
| 1402 | for (i = 0; i < size; ++i) { | ||
| 1403 | char c = buf[i]; | ||
| 1404 | if ((c < ' ' && c != '\t' && c != '\r' && c != '\n') // also allow '\v' '\f'? | ||
| 1405 | || c > 0x7e | ||
| 1406 | ) { | ||
| 1407 | free(buf); | ||
| 1408 | buf = NULL; | ||
| 1409 | break; | ||
| 1410 | } | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | return buf; | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | static void bc_num_setToZero(BcNum *n, size_t scale) | 1405 | static void bc_num_setToZero(BcNum *n, size_t scale) |
| 1417 | { | 1406 | { |
| 1418 | n->len = 0; | 1407 | n->len = 0; |
| @@ -2912,7 +2901,7 @@ static bool bc_lex_more_input(BcLex *l) | |||
| 2912 | size_t str; | 2901 | size_t str; |
| 2913 | bool comment; | 2902 | bool comment; |
| 2914 | 2903 | ||
| 2915 | bc_vec_pop_all(&G.stdin_buffer); | 2904 | bc_vec_pop_all(&G.input_buffer); |
| 2916 | 2905 | ||
| 2917 | // This loop is complex because the vm tries not to send any lines that end | 2906 | // This loop is complex because the vm tries not to send any lines that end |
| 2918 | // with a backslash to the parser. The reason for that is because the parser | 2907 | // with a backslash to the parser. The reason for that is because the parser |
| @@ -2921,18 +2910,18 @@ static bool bc_lex_more_input(BcLex *l) | |||
| 2921 | comment = false; | 2910 | comment = false; |
| 2922 | str = 0; | 2911 | str = 0; |
| 2923 | for (;;) { | 2912 | for (;;) { |
| 2924 | size_t prevlen = G.stdin_buffer.len; | 2913 | size_t prevlen = G.input_buffer.len; |
| 2925 | char *string; | 2914 | char *string; |
| 2926 | 2915 | ||
| 2927 | bc_read_line(&G.stdin_buffer); | 2916 | bc_read_line(&G.input_buffer, G.input_fp); |
| 2928 | // No more input means EOF | 2917 | // No more input means EOF |
| 2929 | if (G.stdin_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) | 2918 | if (G.input_buffer.len <= prevlen + 1) // (we expect +1 for NUL byte) |
| 2930 | break; | 2919 | break; |
| 2931 | 2920 | ||
| 2932 | string = G.stdin_buffer.v + prevlen; | 2921 | string = G.input_buffer.v + prevlen; |
| 2933 | while (*string) { | 2922 | while (*string) { |
| 2934 | char c = *string; | 2923 | char c = *string; |
| 2935 | if (string == G.stdin_buffer.v || string[-1] != '\\') { | 2924 | if (string == G.input_buffer.v || string[-1] != '\\') { |
| 2936 | if (IS_BC) | 2925 | if (IS_BC) |
| 2937 | str ^= (c == '"'); | 2926 | str ^= (c == '"'); |
| 2938 | else { | 2927 | else { |
| @@ -2954,7 +2943,7 @@ static bool bc_lex_more_input(BcLex *l) | |||
| 2954 | } | 2943 | } |
| 2955 | } | 2944 | } |
| 2956 | if (str != 0 || comment) { | 2945 | if (str != 0 || comment) { |
| 2957 | G.stdin_buffer.len--; // backstep over the trailing NUL byte | 2946 | G.input_buffer.len--; // backstep over the trailing NUL byte |
| 2958 | continue; | 2947 | continue; |
| 2959 | } | 2948 | } |
| 2960 | 2949 | ||
| @@ -2963,21 +2952,20 @@ static bool bc_lex_more_input(BcLex *l) | |||
| 2963 | // if it is not, then it's EOF, and looping back | 2952 | // if it is not, then it's EOF, and looping back |
| 2964 | // to bc_read_line() will detect it: | 2953 | // to bc_read_line() will detect it: |
| 2965 | string -= 2; | 2954 | string -= 2; |
| 2966 | if (string >= G.stdin_buffer.v && *string == '\\') { | 2955 | if (string >= G.input_buffer.v && *string == '\\') { |
| 2967 | G.stdin_buffer.len--; | 2956 | G.input_buffer.len--; |
| 2968 | continue; | 2957 | continue; |
| 2969 | } | 2958 | } |
| 2970 | 2959 | ||
| 2971 | break; | 2960 | break; |
| 2972 | } | 2961 | } |
| 2973 | 2962 | ||
| 2974 | l->buf = G.stdin_buffer.v; | 2963 | l->buf = G.input_buffer.v; |
| 2975 | l->i = 0; | 2964 | l->i = 0; |
| 2976 | //bb_error_msg("G.stdin_buffer.len:%d '%s'", G.stdin_buffer.len, G.stdin_buffer.v); | 2965 | // bb_error_msg("G.input_buffer.len:%d '%s'", G.input_buffer.len, G.input_buffer.v); |
| 2977 | l->len = G.stdin_buffer.len - 1; // do not include NUL | 2966 | l->len = G.input_buffer.len - 1; // do not include NUL |
| 2978 | 2967 | ||
| 2979 | G.use_stdin = (l->len != 0); | 2968 | return l->len != 0; |
| 2980 | return G.use_stdin; | ||
| 2981 | } | 2969 | } |
| 2982 | 2970 | ||
| 2983 | static BC_STATUS zbc_lex_next(BcLex *l) | 2971 | static BC_STATUS zbc_lex_next(BcLex *l) |
| @@ -2989,22 +2977,23 @@ static BC_STATUS zbc_lex_next(BcLex *l) | |||
| 2989 | 2977 | ||
| 2990 | l->line += l->newline; | 2978 | l->line += l->newline; |
| 2991 | G.err_line = l->line; | 2979 | G.err_line = l->line; |
| 2992 | 2980 | l->newline = false; | |
| 2993 | l->t.t = BC_LEX_EOF; | ||
| 2994 | //this NL handling is bogus | ||
| 2995 | l->newline = (l->i == l->len); | ||
| 2996 | if (l->newline) { | ||
| 2997 | if (!G.use_stdin || !bc_lex_more_input(l)) | ||
| 2998 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2999 | // here it's guaranteed that l->i is below l->len | ||
| 3000 | l->newline = false; | ||
| 3001 | } | ||
| 3002 | 2981 | ||
| 3003 | // Loop until failure or we don't have whitespace. This | 2982 | // Loop until failure or we don't have whitespace. This |
| 3004 | // is so the parser doesn't get inundated with whitespace. | 2983 | // is so the parser doesn't get inundated with whitespace. |
| 3005 | // Comments are also BC_LEX_WHITESPACE tokens and eaten here. | 2984 | // Comments are also BC_LEX_WHITESPACE tokens and eaten here. |
| 3006 | s = BC_STATUS_SUCCESS; | 2985 | s = BC_STATUS_SUCCESS; |
| 3007 | do { | 2986 | do { |
| 2987 | l->t.t = BC_LEX_EOF; | ||
| 2988 | if (l->i == l->len) { | ||
| 2989 | if (!G.input_fp) | ||
| 2990 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2991 | if (!bc_lex_more_input(l)) { | ||
| 2992 | G.input_fp = NULL; | ||
| 2993 | RETURN_STATUS(BC_STATUS_SUCCESS); | ||
| 2994 | } | ||
| 2995 | // here it's guaranteed that l->i is below l->len | ||
| 2996 | } | ||
| 3008 | dbg_lex("next string to parse:'%.*s'", | 2997 | dbg_lex("next string to parse:'%.*s'", |
| 3009 | (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), | 2998 | (int)(strchrnul(l->buf + l->i, '\n') - (l->buf + l->i)), |
| 3010 | l->buf + l->i); | 2999 | l->buf + l->i); |
| @@ -5351,7 +5340,7 @@ static BC_STATUS zbc_program_read(void) | |||
| 5351 | G.in_read = 1; | 5340 | G.in_read = 1; |
| 5352 | 5341 | ||
| 5353 | bc_char_vec_init(&buf); | 5342 | bc_char_vec_init(&buf); |
| 5354 | bc_read_line(&buf); | 5343 | bc_read_line(&buf, stdin); |
| 5355 | 5344 | ||
| 5356 | bc_parse_create(&parse, BC_PROG_READ); | 5345 | bc_parse_create(&parse, BC_PROG_READ); |
| 5357 | bc_lex_file(&parse.l); | 5346 | bc_lex_file(&parse.l); |
| @@ -6931,60 +6920,44 @@ static BC_STATUS zbc_vm_process(const char *text) | |||
| 6931 | # define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__), BC_STATUS_SUCCESS) | 6920 | # define zbc_vm_process(...) (zbc_vm_process(__VA_ARGS__), BC_STATUS_SUCCESS) |
| 6932 | #endif | 6921 | #endif |
| 6933 | 6922 | ||
| 6934 | static BC_STATUS zbc_vm_file(const char *file) | 6923 | static BC_STATUS zbc_vm_execute_FILE(FILE *fp, const char *filename) |
| 6935 | { | 6924 | { |
| 6936 | // So far bc/dc have no way to include a file from another file, | 6925 | // So far bc/dc have no way to include a file from another file, |
| 6937 | // therefore we know G.prog.file == NULL on entry | 6926 | // therefore we know G.prog.file == NULL on entry |
| 6938 | //const char *sv_file; | 6927 | //const char *sv_file; |
| 6939 | char *data; | ||
| 6940 | BcStatus s; | 6928 | BcStatus s; |
| 6941 | BcFunc *main_func; | ||
| 6942 | BcInstPtr *ip; | ||
| 6943 | |||
| 6944 | data = bc_read_file(file); | ||
| 6945 | if (!data) RETURN_STATUS(bc_error_fmt("file '%s' is not text", file)); | ||
| 6946 | 6929 | ||
| 6947 | //sv_file = G.prog.file; | 6930 | G.prog.file = filename; |
| 6948 | G.prog.file = file; | 6931 | G.input_fp = fp; |
| 6949 | bc_lex_file(&G.prs.l); | 6932 | bc_lex_file(&G.prs.l); |
| 6950 | s = zbc_vm_process(data); | ||
| 6951 | if (s) goto err; | ||
| 6952 | |||
| 6953 | main_func = bc_program_func(BC_PROG_MAIN); | ||
| 6954 | ip = bc_vec_item(&G.prog.stack, 0); | ||
| 6955 | |||
| 6956 | if (main_func->code.len < ip->idx) | ||
| 6957 | s = bc_error_fmt("file '%s' is not executable", file); | ||
| 6958 | 6933 | ||
| 6959 | err: | 6934 | do { |
| 6960 | //G.prog.file = sv_file; | 6935 | s = zbc_vm_process(""); |
| 6936 | // We do not stop looping on errors here if reading stdin. | ||
| 6937 | // Example: start interactive bc and enter "return". | ||
| 6938 | // It should say "'return' not in a function" | ||
| 6939 | // but should not exit. | ||
| 6940 | } while (G.input_fp == stdin); | ||
| 6961 | G.prog.file = NULL; | 6941 | G.prog.file = NULL; |
| 6962 | free(data); | ||
| 6963 | RETURN_STATUS(s); | 6942 | RETURN_STATUS(s); |
| 6964 | } | 6943 | } |
| 6965 | #if ERRORS_ARE_FATAL | 6944 | #if ERRORS_ARE_FATAL |
| 6966 | # define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) | 6945 | # define zbc_vm_execute_FILE(...) (zbc_vm_execute_FILE(__VA_ARGS__), BC_STATUS_SUCCESS) |
| 6967 | #endif | 6946 | #endif |
| 6968 | 6947 | ||
| 6969 | static BC_STATUS zbc_vm_stdin(void) | 6948 | static BC_STATUS zbc_vm_file(const char *file) |
| 6970 | { | 6949 | { |
| 6971 | BcStatus s; | 6950 | BcStatus s; |
| 6951 | FILE *fp; | ||
| 6972 | 6952 | ||
| 6973 | //G.prog.file = NULL; - already is | 6953 | fp = xfopen_for_read(file); |
| 6974 | bc_lex_file(&G.prs.l); | 6954 | s = zbc_vm_execute_FILE(fp, file); |
| 6955 | fclose(fp); | ||
| 6975 | 6956 | ||
| 6976 | G.use_stdin = 1; | ||
| 6977 | do { | ||
| 6978 | s = zbc_vm_process(""); | ||
| 6979 | // We do not stop looping on errors here. | ||
| 6980 | // Example: start interactive bc and enter "return". | ||
| 6981 | // It should say "'return' not in a function" | ||
| 6982 | // but should not exit. | ||
| 6983 | } while (G.use_stdin); | ||
| 6984 | RETURN_STATUS(s); | 6957 | RETURN_STATUS(s); |
| 6985 | } | 6958 | } |
| 6986 | #if ERRORS_ARE_FATAL | 6959 | #if ERRORS_ARE_FATAL |
| 6987 | # define zbc_vm_stdin(...) (zbc_vm_stdin(__VA_ARGS__), BC_STATUS_SUCCESS) | 6960 | # define zbc_vm_file(...) (zbc_vm_file(__VA_ARGS__), BC_STATUS_SUCCESS) |
| 6988 | #endif | 6961 | #endif |
| 6989 | 6962 | ||
| 6990 | #if ENABLE_BC | 6963 | #if ENABLE_BC |
| @@ -7257,7 +7230,7 @@ static BC_STATUS zbc_vm_exec(void) | |||
| 7257 | } | 7230 | } |
| 7258 | 7231 | ||
| 7259 | if (IS_BC || (option_mask32 & BC_FLAG_I)) | 7232 | if (IS_BC || (option_mask32 & BC_FLAG_I)) |
| 7260 | s = zbc_vm_stdin(); | 7233 | s = zbc_vm_execute_FILE(stdin, /*filename:*/ NULL); |
| 7261 | 7234 | ||
| 7262 | RETURN_STATUS(s); | 7235 | RETURN_STATUS(s); |
| 7263 | } | 7236 | } |
| @@ -7287,7 +7260,7 @@ static void bc_program_free(void) | |||
| 7287 | bc_num_free(&G.prog.last); | 7260 | bc_num_free(&G.prog.last); |
| 7288 | bc_num_free(&G.prog.zero); | 7261 | bc_num_free(&G.prog.zero); |
| 7289 | bc_num_free(&G.prog.one); | 7262 | bc_num_free(&G.prog.one); |
| 7290 | bc_vec_free(&G.stdin_buffer); | 7263 | bc_vec_free(&G.input_buffer); |
| 7291 | } | 7264 | } |
| 7292 | 7265 | ||
| 7293 | static void bc_vm_free(void) | 7266 | static void bc_vm_free(void) |
| @@ -7352,7 +7325,7 @@ static void bc_program_init(void) | |||
| 7352 | bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); | 7325 | bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); |
| 7353 | bc_vec_push(&G.prog.stack, &ip); | 7326 | bc_vec_push(&G.prog.stack, &ip); |
| 7354 | 7327 | ||
| 7355 | bc_char_vec_init(&G.stdin_buffer); | 7328 | bc_char_vec_init(&G.input_buffer); |
| 7356 | } | 7329 | } |
| 7357 | 7330 | ||
| 7358 | static int bc_vm_init(const char *env_len) | 7331 | static int bc_vm_init(const char *env_len) |
