vi: code shrink, optimize: do not call count_lines() unless needed
No binary (build failed)
gcc -Wp,-MD,applets/.usage.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Iinclude -Iinclude -o applets/usage applets/usage.c
(log yok)
| @@ -2601,7 +2601,7 @@ static char *get_one_address(char *p, int *result, int *valid) | |
| // Read line addresses for a colon command. The user can enter as | |
| // many as they like but only the last two will be used. | |
| - | static char *get_address(char *p, int *b, int *e, unsigned int *got) |
| + | static char *get_address(char *p, int *b, int *e, unsigned *got) |
| { | |
| int state = GET_ADDRESS; | |
| int valid; | |
| @@ -2849,16 +2849,16 @@ static void colon(char *buf) | |
| } | |
| not_implemented(p); | |
| #else | |
| - | |
| + | char c, *q, *r; |
| + | char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args; |
| + | char *exp = NULL; |
| + | char *useforce; |
| + | int cmdlen; |
| + | int b, e; |
| // check how many addresses we got | |
| # define GOT_ADDRESS (got & 1) | |
| - | # define GOT_RANGE ((got & 3) == 3) |
| - | |
| - | char c, *buf1, *q, *r; |
| - | char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL; |
| - | int i, l, li, b, e; |
| - | unsigned int got; |
| - | int useforce; |
| + | # define GOT_RANGE ((got & 3) == 3) |
| + | unsigned got; |
| // :3154 // if (-e line 3154) goto it else stay put | |
| // :4,33w! foo // write a portion of buffer to file "foo" | |
| @@ -2873,44 +2873,33 @@ static void colon(char *buf) | |
| // :/xyz/ // goto the "xyz" line | |
| // :s/find/replace/ // substitute pattern "find" with "replace" | |
| // :!<cmd> // run <cmd> then return | |
| - | // |
| while (*buf == ':') | |
| buf++; // move past leading colons | |
| - | while (isblank(*buf)) |
| - | buf++; // move past leading blanks |
| - | if (!buf[0] || buf[0] == '"') |
| + | buf = skip_whitespace(buf); // move past leading blanks |
| + | if (!*buf || *buf == '"') |
| goto ret; // ignore empty lines or those starting with '"' | |
| - | li = i = 0; |
| - | b = e = -1; |
| - | got = 0; |
| - | li = count_lines(text, end - 1); |
| fn = current_filename; | |
| - | // look for optional address(es) :. :1 :1,9 :'q,'a :% |
| + | // look for optional address(es) ":." ":1" ":1,9" ":'q,'a" ":%" |
| + | b = e = -1; |
| + | got = 0; |
| buf = get_address(buf, &b, &e, &got); | |
| - | if (buf == NULL) { |
| + | if (buf == NULL) |
| goto ret; | |
| - | } |
| // get the COMMAND into cmd[] | |
| strcpy(cmd, buf); | |
| - | buf1 = cmd; |
| - | while (!isspace(*buf1) && *buf1 != '\0') { |
| - | buf1++; |
| - | } |
| - | cmdend = buf1; |
| + | cmdend = skip_non_whitespace(cmd); |
| // get any ARGuments | |
| - | while (isblank(*buf1)) |
| - | buf1++; |
| - | args = buf1; |
| + | args = skip_whitespace(cmdend); |
| + | //NB: arguments can be accessed in buf[] as well, there is no need to copy them into cmd[]? |
| *cmdend = '\0'; | |
| - | useforce = FALSE; |
| - | if (cmdend > cmd && cmdend[-1] == '!') { |
| - | useforce = TRUE; |
| - | cmdend[-1] = '\0'; // get rid of ! |
| - | } |
| + | useforce = last_char_is(cmd, '!'); |
| + | if (useforce && useforce > cmd) |
| + | *useforce = '\0'; // "CMD!" -> "CMD" (unless single "!") |
| + | |
| // assume the command will want a range, certain commands | |
| // (read, substitute) need to adjust these assumptions | |
| if (!GOT_ADDRESS) { | |
| @@ -2918,7 +2907,10 @@ static void colon(char *buf) | |
| r = end - 1; | |
| } else { | |
| // at least one addr was given, get its details | |
| - | if (e < 0 || e > li) { |
| + | int lines; |
| + | if (e < 0 |
| + | || e > (lines = count_lines(text, end - 1)) |
| + | ) { |
| status_line_bold("Invalid range"); | |
| goto ret; | |
| } | |
| @@ -2928,31 +2920,28 @@ static void colon(char *buf) | |
| // number of the single line the user wants. | |
| // Reset the end pointer to the end of that line. | |
| r = end_line(q); | |
| - | li = 1; |
| } else { | |
| // we were given two addrs. change the | |
| // start pointer to the addr given by user. | |
| - | if (b < 0 || b > li || b > e) { |
| + | if (b < 0 || b > lines || b > e) { |
| status_line_bold("Invalid range"); | |
| goto ret; | |
| } | |
| q = find_line(b); // what line is #b | |
| r = end_line(r); | |
| - | li = e - b + 1; |
| } | |
| } | |
| // ------------ now look for the command ------------ | |
| - | i = strlen(cmd); |
| - | if (i == 0) { // :123CR goto line #123 |
| + | cmdlen = strlen(cmd); |
| + | if (cmdlen == 0) { // ":123<enter>" - goto line #123 |
| if (e >= 0) { | |
| dot = find_line(e); // what line is #e | |
| dot_skip_over_ws(); | |
| } | |
| } | |
| # if ENABLE_FEATURE_ALLOW_EXEC | |
| - | else if (cmd[0] == '!') { // run a cmd |
| + | else if (cmd[0] == '!') { // ":!CMD" - run shell CMD |
| int retcode; | |
| - | // :!ls run the <cmd> |
| if (GOT_ADDRESS) { | |
| status_line_bold("Range not allowed"); | |
| goto ret; | |
| @@ -2974,14 +2963,14 @@ static void colon(char *buf) | |
| e = count_lines(text, dot); | |
| } | |
| status_line("%d", e); | |
| - | } else if (strncmp(cmd, "delete", i) == 0) { // delete lines |
| + | } else if (strncmp(cmd, "delete", cmdlen) == 0) { // delete lines |
| if (!GOT_ADDRESS) { // no addr given- use defaults | |
| q = begin_line(dot); // assume .,. for the range | |
| r = end_line(dot); | |
| } | |
| dot = yank_delete(q, r, WHOLE, YANKDEL, ALLOW_UNDO); // save, then delete lines | |
| dot_skip_over_ws(); | |
| - | } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file |
| + | } else if (strncmp(cmd, "edit", cmdlen) == 0) { // Edit a file |
| int size; | |
| // don't edit, if the current file has been modified | |
| @@ -3012,8 +3001,6 @@ static void colon(char *buf) | |
| reg[YDreg] = NULL; | |
| } | |
| # endif | |
| - | // how many lines in text[]? |
| - | li = count_lines(text, end - 1); |
| status_line("'%s'%s" | |
| IF_FEATURE_VI_READONLY("%s") | |
| " %uL, %uC", | |
| @@ -3022,9 +3009,10 @@ static void colon(char *buf) | |
| IF_FEATURE_VI_READONLY( | |
| ((readonly_mode) ? " [Readonly]" : ""), | |
| ) | |
| - | li, (int)(end - text) |
| + | count_lines(text, end - 1), |
| + | (int)(end - text) |
| ); | |
| - | } else if (strncmp(cmd, "file", i) == 0) { // what File is this |
| + | } else if (strncmp(cmd, "file", cmdlen) == 0) { // what File is this |
| if (e >= 0) { | |
| status_line_bold("No address allowed on this command"); | |
| goto ret; | |
| @@ -3039,14 +3027,14 @@ static void colon(char *buf) | |
| // user wants file status info | |
| last_status_cksum = 0; // force status update | |
| } | |
| - | } else if (strncmp(cmd, "features", i) == 0) { // what features are available |
| + | } else if (strncmp(cmd, "features", cmdlen) == 0) { // what features are available |
| // print out values of all features | |
| go_bottom_and_clear_to_eol(); | |
| cookmode(); | |
| show_help(); | |
| rawmode(); | |
| Hit_Return(); | |
| - | } else if (strncmp(cmd, "list", i) == 0) { // literal print line |
| + | } else if (strncmp(cmd, "list", cmdlen) == 0) { // literal print line |
| if (!GOT_ADDRESS) { // no addr given- use defaults | |
| q = begin_line(dot); // assume .,. for the range | |
| r = end_line(dot); | |
| @@ -3076,9 +3064,9 @@ static void colon(char *buf) | |
| standout_end(); | |
| } | |
| Hit_Return(); | |
| - | } else if (strncmp(cmd, "quit", i) == 0 // quit |
| - | || strncmp(cmd, "next", i) == 0 // edit next file |
| - | || strncmp(cmd, "prev", i) == 0 // edit previous file |
| + | } else if (strncmp(cmd, "quit", cmdlen) == 0 // quit |
| + | || strncmp(cmd, "next", cmdlen) == 0 // edit next file |
| + | || strncmp(cmd, "prev", cmdlen) == 0 // edit previous file |
| ) { | |
| int n; | |
| if (useforce) { | |
| @@ -3113,7 +3101,7 @@ static void colon(char *buf) | |
| optind -= 2; | |
| } | |
| editing = 0; | |
| - | } else if (strncmp(cmd, "read", i) == 0) { // read file into text[] |
| + | } else if (strncmp(cmd, "read", cmdlen) == 0) { // read file into text[] |
| int size, num; | |
| if (args[0]) { | |
| @@ -3145,17 +3133,16 @@ static void colon(char *buf) | |
| } | |
| if (size < 0) | |
| goto ret; // nothing was inserted | |
| - | // how many lines in text[]? |
| - | li = count_lines(q, q + size - 1); |
| status_line("'%s'" | |
| IF_FEATURE_VI_READONLY("%s") | |
| " %uL, %uC", | |
| fn, | |
| IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),) | |
| - | li, size |
| + | count_lines(q, q + size - 1), |
| + | size |
| ); | |
| dot = find_line(num); | |
| - | } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args |
| + | } else if (strncmp(cmd, "rewind", cmdlen) == 0) { // rewind cmd line args |
| if (modified_count && !useforce) { | |
| status_line_bold("No write since last change (:%s! overrides)", cmd); | |
| } else { | |
| @@ -3164,7 +3151,7 @@ static void colon(char *buf) | |
| editing = 0; | |
| } | |
| # if ENABLE_FEATURE_VI_SET | |
| - | } else if (strncmp(cmd, "set", i) == 0) { // set or clear features |
| + | } else if (strncmp(cmd, "set", cmdlen) == 0) { // set or clear features |
| # if ENABLE_FEATURE_VI_SETOPTS | |
| char *argp, *argn, oldch; | |
| # endif | |
| @@ -3192,7 +3179,7 @@ static void colon(char *buf) | |
| # if ENABLE_FEATURE_VI_SETOPTS | |
| argp = args; | |
| while (*argp) { | |
| - | i = 0; |
| + | int i = 0; |
| if (argp[0] == 'n' && argp[1] == 'o') // "noXXX" | |
| i = 2; | |
| argn = skip_non_whitespace(argp); | |
| @@ -3209,6 +3196,7 @@ static void colon(char *buf) | |
| } else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern | |
| char *F, *R, *flags; | |
| size_t len_F, len_R; | |
| + | int i; |
| int gflag = 0; // global replace flag | |
| int subs = 0; // number of substitutions | |
| # if ENABLE_FEATURE_VI_VERBOSE_STATUS | |
| @@ -3272,7 +3260,6 @@ static void colon(char *buf) | |
| # else | |
| len_R = strlen(R); | |
| # endif | |
| - | |
| for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0 | |
| char *ls = q; // orig line start | |
| char *found; | |
| @@ -3344,14 +3331,14 @@ static void colon(char *buf) | |
| regfree(&preg); | |
| # endif | |
| # endif /* FEATURE_VI_SEARCH */ | |
| - | } else if (strncmp(cmd, "version", i) == 0) { // show software version |
| + | } else if (strncmp(cmd, "version", cmdlen) == 0) { // show software version |
| status_line(BB_VER); | |
| - | } else if (strncmp(cmd, "write", i) == 0 // write text to file |
| + | } else if (strncmp(cmd, "write", cmdlen) == 0 // write text to file |
| || strcmp(cmd, "wq") == 0 | |
| || strcmp(cmd, "wn") == 0 | |
| || (cmd[0] == 'x' && !cmd[1]) | |
| ) { | |
| - | int size; |
| + | int size, l; |
| //int forced = FALSE; | |
| // is there a file name to write to? | |
| @@ -3361,8 +3348,10 @@ static void colon(char *buf) | |
| exp = expand_args(args); | |
| if (exp == NULL) | |
| goto ret; | |
| - | if (!useforce && (fn == NULL || strcmp(fn, exp) != 0) && |
| - | stat(exp, &statbuf) == 0) { |
| + | if (!useforce |
| + | && (fn == NULL || strcmp(fn, exp) != 0) |
| + | && stat(exp, &statbuf) == 0 |
| + | ) { |
| status_line_bold("File exists (:w! overrides)"); | |
| goto ret; | |
| } | |
| @@ -3381,12 +3370,10 @@ static void colon(char *buf) | |
| // system(syscmd); | |
| // forced = TRUE; | |
| //} | |
| + | size = l = 0; |
| if (modified_count != 0 || cmd[0] != 'x') { | |
| size = r - q + 1; | |
| l = file_write(fn, q, r); | |
| - | } else { |
| - | size = 0; |
| - | l = 0; |
| } | |
| //if (useforce && forced) { | |
| // chmod u-w | |
| @@ -3399,8 +3386,8 @@ static void colon(char *buf) | |
| status_line_bold_errno(fn); | |
| } else { | |
| // how many lines written | |
| - | li = count_lines(q, q + l - 1); |
| - | status_line("'%s' %uL, %uC", fn, li, l); |
| + | int lines = count_lines(q, q + l - 1); |
| + | status_line("'%s' %uL, %uC", fn, lines, l); |
| if (l == size) { | |
| if (q == text && q + l == end) { | |
| modified_count = 0; | |
| @@ -3425,15 +3412,16 @@ static void colon(char *buf) | |
| } | |
| } | |
| # if ENABLE_FEATURE_VI_YANKMARK | |
| - | } else if (strncmp(cmd, "yank", i) == 0) { // yank lines |
| + | } else if (strncmp(cmd, "yank", cmdlen) == 0) { // yank lines |
| + | int lines; |
| if (!GOT_ADDRESS) { // no addr given- use defaults | |
| q = begin_line(dot); // assume .,. for the range | |
| r = end_line(dot); | |
| } | |
| text_yank(q, r, YDreg, WHOLE); | |
| - | li = count_lines(q, r); |
| + | lines = count_lines(q, r); |
| status_line("Yank %d lines (%d chars) into [%c]", | |
| - | li, strlen(reg[YDreg]), what_reg()); |
| + | lines, strlen(reg[YDreg]), what_reg()); |
| # endif | |
| } else { | |
| // cmd unknown | |