/* Globals. Split in two parts so that first one is addressed
- * with (mostly short) negative offsets */
+ * with (mostly short) negative offsets.
+ * NB: it's unsafe to put members of type "double"
+ * into globals2 (gcc may fail to align them).
+ */
struct globals {
+ double t_double;
chain beginseq, mainseq, endseq;
chain *seq;
node *break_ptr, *continue_ptr;
tsplitter exec_builtin__tspl;
/* biggest and least used members go last */
- double t_double;
tsplitter fsplitter, rsplitter;
};
#define G1 (ptr_to_globals[-1])
#define G (*(struct globals2 *)ptr_to_globals)
/* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
-/* char G1size[sizeof(G1)]; - 0x6c */
-/* char Gsize[sizeof(G)]; - 0x1cc */
+/*char G1size[sizeof(G1)]; - 0x74 */
+/*char Gsize[sizeof(G)]; - 0x1c4 */
/* Trying to keep most of members accessible with short offsets: */
-/* char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
+/*char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
+#define t_double (G1.t_double )
#define beginseq (G1.beginseq )
#define mainseq (G1.mainseq )
#define endseq (G1.endseq )
#define t_info (G.t_info )
#define t_tclass (G.t_tclass )
#define t_string (G.t_string )
-#define t_double (G.t_double )
#define t_lineno (G.t_lineno )
#define t_rollback (G.t_rollback )
#define intvar (G.intvar )
memset(vp, 0, sizeof(*vp));
}
-static void syntax_error(const char *const message) NORETURN;
-static void syntax_error(const char *const message)
+static void syntax_error(const char *message) NORETURN;
+static void syntax_error(const char *message)
{
bb_error_msg_and_die("%s:%i: %s", g_progname, g_lineno, message);
}
hash_rebuild(hash);
l = strlen(name) + 1;
- hi = xzalloc(sizeof(hash_item) + l);
- memcpy(hi->name, name, l);
+ hi = xzalloc(sizeof(*hi) + l);
+ strcpy(hi->name, name);
idx = hashidx(name) % hash->csize;
hi->next = hash->items[idx];
*/
static regex_t *as_regex(node *op, regex_t *preg)
{
+ int cflags;
var *v;
const char *s;
}
v = nvalloc(1);
s = getvar_s(evaluate(op, v));
- xregcomp(preg, s, icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED);
+
+ cflags = icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED;
+ /* Testcase where REG_EXTENDED fails (unpaired '{'):
+ * echo Hi | awk 'gsub("@(samp|code|file)\{","");'
+ * gawk 3.1.5 eats this. We revert to ~REG_EXTENDED
+ * (maybe gsub is not supposed to use REG_EXTENDED?).
+ */
+ if (regcomp(preg, s, cflags)) {
+ cflags &= ~REG_EXTENDED;
+ xregcomp(preg, s, cflags);
+ }
nvfree(v);
return preg;
}
n++; /* we saw yet another delimiter */
} else {
pmatch[0].rm_eo = l;
- if (s[l]) pmatch[0].rm_eo++;
+ if (s[l])
+ pmatch[0].rm_eo++;
}
memcpy(s1, s, l);
- s1[l] = '\0';
+ /* make sure we remove *all* of the separator chars */
+ do {
+ s1[l] = '\0';
+ } while (++l < pmatch[0].rm_eo);
nextword(&s1);
s += pmatch[0].rm_eo;
} while (*s);