Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/editors/awk.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/editors/awk.c
r3232 r3621 8 8 */ 9 9 10 //config:config AWK 11 //config: bool "awk" 12 //config: default y 13 //config: help 14 //config: Awk is used as a pattern scanning and processing language. This is 15 //config: the BusyBox implementation of that programming language. 16 //config: 17 //config:config FEATURE_AWK_LIBM 18 //config: bool "Enable math functions (requires libm)" 19 //config: default y 20 //config: depends on AWK 21 //config: help 22 //config: Enable math functions of the Awk programming language. 23 //config: NOTE: This will require libm to be present for linking. 24 //config: 25 //config:config FEATURE_AWK_GNU_EXTENSIONS 26 //config: bool "Enable a few GNU extensions" 27 //config: default y 28 //config: depends on AWK 29 //config: help 30 //config: Enable a few features from gawk: 31 //config: * command line option -e AWK_PROGRAM 32 //config: * simultaneous use of -f and -e on the command line. 33 //config: This enables the use of awk library files. 34 //config: Ex: awk -f mylib.awk -e '{print myfunction($1);}' ... 35 36 //applet:IF_AWK(APPLET_NOEXEC(awk, awk, BB_DIR_USR_BIN, BB_SUID_DROP, awk)) 37 38 //kbuild:lib-$(CONFIG_AWK) += awk.o 39 10 40 //usage:#define awk_trivial_usage 11 41 //usage: "[OPTIONS] [AWK_PROGRAM] [FILE]..." … … 14 44 //usage: "\n -F SEP Use SEP as field separator" 15 45 //usage: "\n -f FILE Read program from FILE" 46 //usage: IF_FEATURE_AWK_GNU_EXTENSIONS( 47 //usage: "\n -e AWK_PROGRAM" 48 //usage: ) 16 49 17 50 #include "libbb.h" … … 39 72 40 73 74 #define OPTSTR_AWK \ 75 "F:v:f:" \ 76 IF_FEATURE_AWK_GNU_EXTENSIONS("e:") \ 77 "W:" 78 #define OPTCOMPLSTR_AWK \ 79 "v::f::" \ 80 IF_FEATURE_AWK_GNU_EXTENSIONS("e::") 81 enum { 82 OPTBIT_F, /* define field separator */ 83 OPTBIT_v, /* define variable */ 84 OPTBIT_f, /* pull in awk program from file */ 85 IF_FEATURE_AWK_GNU_EXTENSIONS(OPTBIT_e,) /* -e AWK_PROGRAM */ 86 OPTBIT_W, /* -W ignored */ 87 OPT_F = 1 << OPTBIT_F, 88 OPT_v = 1 << OPTBIT_v, 89 OPT_f = 1 << OPTBIT_f, 90 OPT_e = IF_FEATURE_AWK_GNU_EXTENSIONS((1 << OPTBIT_e)) + 0, 91 OPT_W = 1 << OPTBIT_W 92 }; 41 93 42 94 #define MAXVARFMT 240 … … 156 208 /* simple token classes */ 157 209 /* Order and hex values are very important!!! See next_token() */ 158 #define TC_SEQSTART 1/* ( */210 #define TC_SEQSTART (1 << 0) /* ( */ 159 211 #define TC_SEQTERM (1 << 1) /* ) */ 160 212 #define TC_REGEXP (1 << 2) /* /.../ */ … … 176 228 #define TC_ELSE (1 << 18) 177 229 #define TC_BUILTIN (1 << 19) 178 #define TC_GETLINE (1 << 20) 179 #define TC_FUNCDECL (1 << 21) /* `function' `func' */ 180 #define TC_BEGIN (1 << 22) 181 #define TC_END (1 << 23) 182 #define TC_EOF (1 << 24) 183 #define TC_VARIABLE (1 << 25) 184 #define TC_ARRAY (1 << 26) 185 #define TC_FUNCTION (1 << 27) 186 #define TC_STRING (1 << 28) 187 #define TC_NUMBER (1 << 29) 230 /* This costs ~50 bytes of code. 231 * A separate class to support deprecated "length" form. If we don't need that 232 * (i.e. if we demand that only "length()" with () is valid), then TC_LENGTH 233 * can be merged with TC_BUILTIN: 234 */ 235 #define TC_LENGTH (1 << 20) 236 #define TC_GETLINE (1 << 21) 237 #define TC_FUNCDECL (1 << 22) /* `function' `func' */ 238 #define TC_BEGIN (1 << 23) 239 #define TC_END (1 << 24) 240 #define TC_EOF (1 << 25) 241 #define TC_VARIABLE (1 << 26) 242 #define TC_ARRAY (1 << 27) 243 #define TC_FUNCTION (1 << 28) 244 #define TC_STRING (1 << 29) 245 #define TC_NUMBER (1 << 30) 188 246 189 247 #define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2) … … 191 249 /* combined token classes */ 192 250 #define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN) 193 #define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)251 //#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST) 194 252 #define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \ 195 | TC_BUILTIN | TC_GETLINE | TC_SEQSTART | TC_STRING | TC_NUMBER) 253 | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ 254 | TC_SEQSTART | TC_STRING | TC_NUMBER) 196 255 197 256 #define TC_STATEMNT (TC_STATX | TC_WHILE) … … 199 258 200 259 /* word tokens, cannot mean something else if not expected */ 201 #define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE | TC_BUILTIN \ 202 | TC_GETLINE | TC_FUNCDECL | TC_BEGIN | TC_END) 260 #define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE \ 261 | TC_BUILTIN | TC_LENGTH | TC_GETLINE \ 262 | TC_FUNCDECL | TC_BEGIN | TC_END) 203 263 204 264 /* discard newlines after these */ … … 295 355 #define NTCC '\377' 296 356 297 #define OC_B OC_BUILTIN298 299 357 static const char tokenlist[] ALIGN1 = 300 "\1(" NTC 301 "\1)" NTC 302 "\1/" NTC /* REGEXP */303 "\2>>" "\1>" "\1|" NTC /* OUTRDR */304 "\2++" "\2--" NTC /* UOPPOST */305 "\2++" "\2--" "\1$" NTC /* UOPPRE1 */306 "\2==" "\1=" "\2+=" "\2-=" /* BINOPX */358 "\1(" NTC /* TC_SEQSTART */ 359 "\1)" NTC /* TC_SEQTERM */ 360 "\1/" NTC /* TC_REGEXP */ 361 "\2>>" "\1>" "\1|" NTC /* TC_OUTRDR */ 362 "\2++" "\2--" NTC /* TC_UOPPOST */ 363 "\2++" "\2--" "\1$" NTC /* TC_UOPPRE1 */ 364 "\2==" "\1=" "\2+=" "\2-=" /* TC_BINOPX */ 307 365 "\2*=" "\2/=" "\2%=" "\2^=" 308 366 "\1+" "\1-" "\3**=" "\2**" … … 311 369 "\1<" "\2!~" "\1~" "\2&&" 312 370 "\2||" "\1?" "\1:" NTC 313 "\2in" NTC 314 "\1," NTC 315 "\1|" NTC 316 "\1+" "\1-" "\1!" NTC /* UOPPRE2 */317 "\1]" NTC 318 "\1{" NTC 319 "\1}" NTC 320 "\1;" NTC 321 "\1\n" NTC 322 "\2if" "\2do" "\3for" "\5break" /* STATX */371 "\2in" NTC /* TC_IN */ 372 "\1," NTC /* TC_COMMA */ 373 "\1|" NTC /* TC_PIPE */ 374 "\1+" "\1-" "\1!" NTC /* TC_UOPPRE2 */ 375 "\1]" NTC /* TC_ARRTERM */ 376 "\1{" NTC /* TC_GRPSTART */ 377 "\1}" NTC /* TC_GRPTERM */ 378 "\1;" NTC /* TC_SEMICOL */ 379 "\1\n" NTC /* TC_NEWLINE */ 380 "\2if" "\2do" "\3for" "\5break" /* TC_STATX */ 323 381 "\10continue" "\6delete" "\5print" 324 382 "\6printf" "\4next" "\10nextfile" 325 383 "\6return" "\4exit" NTC 326 "\5while" NTC 327 "\4else" NTC 328 329 "\3and" "\5compl" "\6lshift" "\2or" 384 "\5while" NTC /* TC_WHILE */ 385 "\4else" NTC /* TC_ELSE */ 386 "\3and" "\5compl" "\6lshift" "\2or" /* TC_BUILTIN */ 330 387 "\6rshift" "\3xor" 331 "\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */388 "\5close" "\6system" "\6fflush" "\5atan2" 332 389 "\3cos" "\3exp" "\3int" "\3log" 333 390 "\4rand" "\3sin" "\4sqrt" "\5srand" 334 "\6gensub" "\4gsub" "\5index" "\6length"391 "\6gensub" "\4gsub" "\5index" /* "\6length" was here */ 335 392 "\5match" "\5split" "\7sprintf" "\3sub" 336 393 "\6substr" "\7systime" "\10strftime" "\6mktime" 337 394 "\7tolower" "\7toupper" NTC 338 "\7getline" NTC 339 "\4func" "\10function" NTC 340 "\5BEGIN" NTC 341 "\3END" 395 "\6length" NTC /* TC_LENGTH */ 396 "\7getline" NTC /* TC_GETLINE */ 397 "\4func" "\10function" NTC /* TC_FUNCDECL */ 398 "\5BEGIN" NTC /* TC_BEGIN */ 399 "\3END" /* TC_END */ 342 400 /* compiler adds trailing "\0" */ 343 401 ; 402 403 #define OC_B OC_BUILTIN 344 404 345 405 static const uint32_t tokeninfo[] = { … … 357 417 OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55), 358 418 OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':', 359 OC_IN|SV|P(49), /* in*/419 OC_IN|SV|P(49), /* TC_IN */ 360 420 OC_COMMA|SS|P(80), 361 421 OC_PGETLINE|SV|P(37), … … 372 432 ST_WHILE, 373 433 0, /* else */ 374 375 434 OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83), 376 435 OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83), … … 378 437 OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg, 379 438 OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr, 380 OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), OC_FBLTIN|Sx|F_le,439 OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */ 381 440 OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6), 382 441 OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), 383 442 OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), 443 OC_FBLTIN|Sx|F_le, /* TC_LENGTH */ 384 444 OC_GETLINE|SV|P(0), 385 445 0, 0, 386 446 0, 387 0 /* END */447 0 /* TC_END */ 388 448 }; 389 449 … … 1009 1069 if (t_rollback) { 1010 1070 t_rollback = FALSE; 1011 1012 1071 } else if (concat_inserted) { 1013 1072 concat_inserted = FALSE; 1014 1073 t_tclass = save_tclass; 1015 1074 t_info = save_info; 1016 1017 1075 } else { 1018 1076 p = g_pos; … … 1030 1088 tc = TC_EOF; 1031 1089 debug_printf_parse("%s: token found: TC_EOF\n", __func__); 1032 1033 1090 } else if (*p == '\"') { 1034 1091 /* it's a string */ … … 1046 1103 tc = TC_STRING; 1047 1104 debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string); 1048 1049 1105 } else if ((expected & TC_REGEXP) && *p == '/') { 1050 1106 /* it's regexp */ … … 1079 1135 tc = TC_NUMBER; 1080 1136 debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double); 1081 1082 1137 } else { 1083 1138 /* search for something known */ … … 1156 1211 1157 1212 /* Are we ready for this? */ 1158 if (!(ltclass & expected)) 1213 if (!(ltclass & expected)) { 1159 1214 syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ? 1160 1215 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN); 1216 } 1161 1217 1162 1218 return ltclass; … … 1325 1381 cn->l.n = condition(); 1326 1382 break; 1383 1384 case TC_LENGTH: 1385 debug_printf_parse("%s: TC_LENGTH\n", __func__); 1386 next_token(TC_SEQSTART | TC_OPTERM | TC_GRPTERM); 1387 rollback_token(); 1388 if (t_tclass & TC_SEQSTART) { 1389 /* It was a "(" token. Handle just like TC_BUILTIN */ 1390 cn->l.n = condition(); 1391 } 1392 break; 1327 1393 } 1328 1394 } … … 1489 1555 n = chain_node(OC_EXEC); 1490 1556 n->a.n = break_ptr; 1557 chain_expr(t_info); 1491 1558 break; 1492 1559 … … 1495 1562 n = chain_node(OC_EXEC); 1496 1563 n->a.n = continue_ptr; 1564 chain_expr(t_info); 1497 1565 break; 1498 1566 … … 1527 1595 seq = &beginseq; 1528 1596 chain_group(); 1529 1530 1597 } else if (tclass & TC_END) { 1531 1598 debug_printf_parse("%s: TC_END\n", __func__); 1532 1599 seq = &endseq; 1533 1600 chain_group(); 1534 1535 1601 } else if (tclass & TC_FUNCDECL) { 1536 1602 debug_printf_parse("%s: TC_FUNCDECL\n", __func__); … … 1550 1616 chain_group(); 1551 1617 clear_array(ahash); 1552 1553 1618 } else if (tclass & TC_OPSEQ) { 1554 1619 debug_printf_parse("%s: TC_OPSEQ\n", __func__); … … 1565 1630 } 1566 1631 cn->r.n = mainseq.last; 1567 1568 1632 } else /* if (tclass & TC_GRPSTART) */ { 1569 1633 debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__); … … 1826 1890 1827 1891 mk_splitter(getvar_s(v), &fsplitter); 1828 1829 1892 } else if (v == intvar[RS]) { 1830 1893 mk_splitter(getvar_s(v), &rsplitter); 1831 1832 1894 } else if (v == intvar[IGNORECASE]) { 1833 1895 icase = istrue(v); 1834 1835 1896 } else { /* $n */ 1836 1897 n = getvar_i(intvar[NF]); … … 2016 2077 const char *s = format; 2017 2078 2018 if (int_as_int && n == ( int)n) {2019 r = snprintf(b, size, "% d", (int)n);2079 if (int_as_int && n == (long long)n) { 2080 r = snprintf(b, size, "%lld", (long long)n); 2020 2081 } else { 2021 2082 do { c = *s; } while (c && *++s); … … 2662 2723 const char *sv_progname; 2663 2724 2664 if (!op->r.f->body.first) 2725 /* The body might be empty, still has to eval the args */ 2726 if (!op->r.n->info && !op->r.f->body.first) 2665 2727 syntax_error(EMSG_UNDEF_FUNC); 2666 2728 … … 2733 2795 switch (opn) { 2734 2796 case F_in: 2735 R_d = ( int)L_d;2797 R_d = (long long)L_d; 2736 2798 break; 2737 2799 … … 2784 2846 2785 2847 case F_le: 2786 if (!op1) 2848 debug_printf_eval("length: L.s:'%s'\n", L.s); 2849 if (!op1) { 2787 2850 L.s = getvar_s(intvar[F0]); 2851 debug_printf_eval("length: L.s='%s'\n", L.s); 2852 } 2853 else if (L.v->type & VF_ARRAY) { 2854 R_d = L.v->x.array->nel; 2855 debug_printf_eval("length: array_len:%d\n", L.v->x.array->nel); 2856 break; 2857 } 2788 2858 R_d = strlen(L.s); 2789 2859 break; … … 2931 3001 if (R_d == 0) 2932 3002 syntax_error(EMSG_DIV_BY_ZERO); 2933 L_d -= ( int)(L_d / R_d) * R_d;3003 L_d -= (long long)(L_d / R_d) * R_d; 2934 3004 break; 2935 3005 } … … 3079 3149 llist_t *list_v = NULL; 3080 3150 llist_t *list_f = NULL; 3151 #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS 3152 llist_t *list_e = NULL; 3153 #endif 3081 3154 int i, j; 3082 3155 var *v; … … 3137 3210 } 3138 3211 } 3139 opt_complementary = "v::f::"; /* -v and -f can occur multiple times */3140 opt = getopt32(argv, "F:v:f:W:", &opt_F, &list_v, &list_f,NULL);3212 opt_complementary = OPTCOMPLSTR_AWK; 3213 opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL); 3141 3214 argv += optind; 3142 3215 argc -= optind; 3143 if (opt & 0x1) { /* -F */ 3216 if (opt & OPT_W) 3217 bb_error_msg("warning: option -W is ignored"); 3218 if (opt & OPT_F) { 3144 3219 unescape_string_in_place(opt_F); 3145 3220 setvar_s(intvar[FS], opt_F); 3146 3221 } 3147 while (list_v) { /* -v */3222 while (list_v) { 3148 3223 if (!is_assignment(llist_pop(&list_v))) 3149 3224 bb_show_usage(); 3150 3225 } 3151 if (list_f) { /* -f */ 3152 do { 3153 char *s = NULL; 3154 FILE *from_file; 3155 3156 g_progname = llist_pop(&list_f); 3157 from_file = xfopen_stdin(g_progname); 3158 /* one byte is reserved for some trick in next_token */ 3159 for (i = j = 1; j > 0; i += j) { 3160 s = xrealloc(s, i + 4096); 3161 j = fread(s + i, 1, 4094, from_file); 3162 } 3163 s[i] = '\0'; 3164 fclose(from_file); 3165 parse_program(s + 1); 3166 free(s); 3167 } while (list_f); 3168 argc++; 3169 } else { // no -f: take program from 1st parameter 3170 if (!argc) 3226 while (list_f) { 3227 char *s = NULL; 3228 FILE *from_file; 3229 3230 g_progname = llist_pop(&list_f); 3231 from_file = xfopen_stdin(g_progname); 3232 /* one byte is reserved for some trick in next_token */ 3233 for (i = j = 1; j > 0; i += j) { 3234 s = xrealloc(s, i + 4096); 3235 j = fread(s + i, 1, 4094, from_file); 3236 } 3237 s[i] = '\0'; 3238 fclose(from_file); 3239 parse_program(s + 1); 3240 free(s); 3241 } 3242 g_progname = "cmd. line"; 3243 #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS 3244 while (list_e) { 3245 parse_program(llist_pop(&list_e)); 3246 } 3247 #endif 3248 if (!(opt & (OPT_f | OPT_e))) { 3249 if (!*argv) 3171 3250 bb_show_usage(); 3172 g_progname = "cmd. line";3173 3251 parse_program(*argv++); 3174 } 3175 if (opt & 0x8) // -W 3176 bb_error_msg("warning: option -W is ignored"); 3252 argc--; 3253 } 3177 3254 3178 3255 /* fill in ARGV array */ 3179 setvar_i(intvar[ARGC], argc );3256 setvar_i(intvar[ARGC], argc + 1); 3180 3257 setari_u(intvar[ARGV], 0, "awk"); 3181 3258 i = 0;
Note:
See TracChangeset
for help on using the changeset viewer.