[git commit] join: code shrink by making some variables "global"
Denys Vlasenko
vda.linux at googlemail.com
Wed Jul 8 12:38:07 UTC 2026
commit: https://git.busybox.net/busybox/commit/?id=8f0533c576964c99e0d9d573942d845122d56863
branch: https://git.busybox.net/busybox/log/?h=master
function old new delta
readfields 442 437 -5
printfields 462 457 -5
join_main 843 760 -83
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-93) Total: -93 bytes
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
coreutils/join.c | 108 +++++++++++++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 50 deletions(-)
diff --git a/coreutils/join.c b/coreutils/join.c
index aee944c50..34b4437d3 100644
--- a/coreutils/join.c
+++ b/coreutils/join.c
@@ -33,6 +33,7 @@
#include "libbb.h"
#include "unicode.h"
+#include "common_bufsiz.h"
/* This is a NOEXEC applet. Be very careful! */
@@ -52,8 +53,24 @@ typedef struct {
int linecap; /* current capacity of lines array */
} FDAT;
+/* "globals" can be made local to main(), but then passing them
+ down the callchains as parameters requires ~90 bytes of code (on x86).
+ */
+struct globals {
+ int *format; // = NULL;
+ const char *empty_str;
+ /* \0 can't be separator, 0 means: "whitespace+" pattern */
+ char sep; // = 0;
+} FIX_ALIASING;
+#define G (*(struct globals*)bb_common_bufsiz1)
+#define INIT_G() do { \
+ setup_common_bufsiz(); \
+ /* we have to zero it out because of NOEXEC */ \
+ memset(&G, 0, sizeof(G)); \
+} while (0)
+
/* split s by sep, and put the results into *curr */
-static void field_split(char *s, char sep, LINE *curr)
+static void field_split(char *s, LINE *curr)
{
/* compare awk_split from editors/awk.c */
int n;
@@ -68,8 +85,8 @@ static void field_split(char *s, char sep, LINE *curr)
curr->line = s;
n = 0;
- if (sep != '\0') { /* single-character split */
- while ((s1 = strchr(ps, sep)) != NULL) {
+ if (G.sep != '\0') { /* single-character split */
+ while ((s1 = strchr(ps, G.sep)) != NULL) {
sl[n] = ps;
*s1 = '\0';
ps = s1 + 1;
@@ -123,7 +140,7 @@ static void freelines(FDAT *f)
f->field = "";
}
-static void readfields(char sep, FDAT *f)
+static void readfields(FDAT *f)
{
LINE curr = { .line = NULL, .fields = NULL, .fieldcount = 0 };
char *line;
@@ -144,7 +161,7 @@ static void readfields(char sep, FDAT *f)
return;
}
- field_split(line, sep, &curr);
+ field_split(line, &curr);
}
if (f->idx >= curr.fieldcount)
@@ -171,14 +188,14 @@ static void readfields(char sep, FDAT *f)
}
}
-static inline const char *fieldorempty(const char *field, const char *empty_str)
+static inline const char *fieldorempty(const char *field)
{
if (*field == '\0')
- return empty_str;
+ return G.empty_str;
return field;
}
-static void printfields(int *format, const char *empty_str, char sep, FDAT *f1, FDAT *f2)
+static void printfields(FDAT *f1, FDAT *f2)
{
const char *field = (f1 == NULL) ? f2->field : f1->field;
@@ -189,19 +206,19 @@ static void printfields(int *format, const char *empty_str, char sep, FDAT *f1,
int format_idx;
int *formatcurr;
bool first;
+ char sep;
LINE *l1;
LINE *l2;
- if (sep == '\0')
- sep = ' ';
+ sep = (G.sep == '\0') ? ' ' : G.sep;
for (linef1 = 0; linef1 < (f1 ? f1->linecount : 1); linef1++) {
l1 = f1 ? &f1->lines[linef1] : NULL;
for (linef2 = 0; linef2 < (f2 ? f2->linecount : 1); linef2++) {
l2 = f2 ? &f2->lines[linef2] : NULL;
- if (format) {
+ if (G.format) {
/*
Format is a sort of null-terminated array:
They are indexed by [n] for file number and [n + 1] for field number.
@@ -209,7 +226,7 @@ static void printfields(int *format, const char *empty_str, char sep, FDAT *f1,
If file number is neither 1 nor 2 then we have the join field.
*/
first = true;
- formatcurr = format;
+ formatcurr = G.format;
while (formatcurr[0]) {
if (first)
first = false;
@@ -221,28 +238,28 @@ static void printfields(int *format, const char *empty_str, char sep, FDAT *f1,
if (format_fl == 1) {
if (l1 != NULL && l1->fieldcount > format_idx)
- fputs_stdout(fieldorempty(l1->fields[format_idx], empty_str));
+ fputs_stdout(fieldorempty(l1->fields[format_idx]));
else
- fputs_stdout(empty_str);
+ fputs_stdout(G.empty_str);
} else if (format_fl == 2) {
if (l2 != NULL && l2->fieldcount > format_idx)
- fputs_stdout(fieldorempty(l2->fields[format_idx], empty_str));
+ fputs_stdout(fieldorempty(l2->fields[format_idx]));
else
- fputs_stdout(empty_str);
+ fputs_stdout(G.empty_str);
} else
- fputs_stdout(fieldorempty(field, empty_str));
+ fputs_stdout(fieldorempty(field));
formatcurr += 2;
}
} else {
- fputs_stdout(fieldorempty(field, empty_str));
+ fputs_stdout(fieldorempty(field));
fn = 0;
if (l1 != NULL)
while (l1->fields[fn]) {
if (fn != f1->idx) {
bb_putchar(sep);
- fputs_stdout(fieldorempty(l1->fields[fn], empty_str));
+ fputs_stdout(fieldorempty(l1->fields[fn]));
}
fn++;
}
@@ -252,7 +269,7 @@ static void printfields(int *format, const char *empty_str, char sep, FDAT *f1,
while (l2->fields[fn]) {
if (fn != f2->idx) {
bb_putchar(sep);
- fputs_stdout(fieldorempty(l2->fields[fn], empty_str));
+ fputs_stdout(fieldorempty(l2->fields[fn]));
}
fn++;
}
@@ -262,7 +279,7 @@ static void printfields(int *format, const char *empty_str, char sep, FDAT *f1,
}
}
-static void parsejformat(int **format_p, const char *format_str)
+static void parsejformat(const char *format_str)
{
int *format;
int field_idx;
@@ -278,7 +295,7 @@ static void parsejformat(int **format_p, const char *format_str)
which ends up being (strlen + 1) / 2
and then we need to have two for each entry plus one for the terminator.
( (strlen+1) / 2 * 2 is optimized out in the alloc) */
- *format_p = format = xzalloc(sizeof(format[0]) * ((strlen(format_str) + 1) + 1));
+ G.format = format = xzalloc(sizeof(format[0]) * ((strlen(format_str) + 1) + 1));
/* default split: skip the initial whitespace and then any run
of non-whitespace characters is a field */
@@ -328,25 +345,17 @@ int join_main(int argc UNUSED_PARAM, char **argv)
bool print2unpaired; // = false;
bool printpaired;
- int *format; // = NULL;
-
FDAT f1; // = { };
FDAT f2; // = { };
-
- /* We can't use \0 as a real separator, so this stands in for the whitespace+ pattern */
- char sep; // = 0;
} L;
#define unpaired_list L.unpaired_list
#define format_str L.format_str
#define print1unpaired L.print1unpaired
#define print2unpaired L.print2unpaired
#define printpaired L.printpaired
-#define format L.format
#define f1 L.f1
#define f2 L.f2
-#define sep L.sep
- const char *empty_str;
char *separator;
uint32_t opts;
/* Must match getopt32 call */
@@ -360,10 +369,9 @@ int join_main(int argc UNUSED_PARAM, char **argv)
FLAG_FIELD_2 = (1 << 6),
};
+ INIT_G();
+ G.empty_str = "";
memset(&L, 0, sizeof(L));
-
- empty_str = "";
-
init_unicode();
opts = getopt32(argv,
@@ -375,7 +383,7 @@ int join_main(int argc UNUSED_PARAM, char **argv)
"\0""=2:a--v:v--a",
&unpaired_list,
&unpaired_list,
- &empty_str,
+ &G.empty_str,
&format_str,
&separator,
&f1.idx,
@@ -407,11 +415,11 @@ int join_main(int argc UNUSED_PARAM, char **argv)
if (separator[0] && separator[1])
bb_simple_error_msg_and_die("separators are single characters");
- sep = *separator;
+ G.sep = *separator;
}
if (opts & FLAG_LIST_OUTPUT)
- parsejformat(&format, format_str);
+ parsejformat(format_str);
f1.fp = xfopen_stdin(argv[0]);
f2.fp = xfopen_stdin(argv[1]);
@@ -478,42 +486,42 @@ int join_main(int argc UNUSED_PARAM, char **argv)
*/
- readfields(sep, &f1);
- readfields(sep, &f2);
+ readfields(&f1);
+ readfields(&f2);
while (f1.linecount != 0 && f2.linecount != 0) {
int res = strcmp(f1.field, f2.field);
if (res == 0) {
if (printpaired)
- printfields(format, empty_str, sep, &f1, &f2);
+ printfields(&f1, &f2);
- readfields(sep, &f1);
- readfields(sep, &f2);
+ readfields(&f1);
+ readfields(&f2);
} else if (res < 0) {
if (print1unpaired)
- printfields(format, empty_str, sep, &f1, NULL);
+ printfields(&f1, NULL);
- readfields(sep, &f1);
+ readfields(&f1);
} else {
if (print2unpaired)
- printfields(format, empty_str, sep, NULL, &f2);
+ printfields(NULL, &f2);
- readfields(sep, &f2);
+ readfields(&f2);
}
}
if (print1unpaired) {
while (f1.linecount != 0) {
- printfields(format, empty_str, sep, &f1, NULL);
- readfields(sep, &f1);
+ printfields(&f1, NULL);
+ readfields(&f1);
}
}
if (print2unpaired) {
while (f2.linecount != 0) {
- printfields(format, empty_str, sep, NULL, &f2);
- readfields(sep, &f2);
+ printfields(NULL, &f2);
+ readfields(&f2);
}
}
@@ -528,7 +536,7 @@ int join_main(int argc UNUSED_PARAM, char **argv)
free(f2.lines);
}
- free(format);
+ free(G.format);
fclose_if_not_stdin(f1.fp);
fclose_if_not_stdin(f2.fp);
More information about the busybox-cvs
mailing list