lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi all,

We are upgrading from Lua 3.2 to Lua 4.0, and I noticed the following problem, for which I have a proposed solution.

The lua command driver (src/lua/lua.c) handles variable assignments as part of option parsing. Unfortunately, it does this in way that clobbers the option value (as observed by getargs()).

Here's the original code:

static void assign (char *arg) {
  char *eq = strchr(arg, '=');
  *eq = '\0';  /* spilt `arg' in two strings (name & value) */
  lua_pushstring(L, eq+1);
  lua_setglobal(L, arg);
}

The problem is at the split.  It clobbers the argv[] value.

To see this, try:

lua FOO=baz -i
> print(getargs()[1])
FOO

I argue that this should print
FOO=baz

It is not difficult to fix this, at the cost of a little code. While I was at it, I changed this to reject:
	lua =baz
which I think is not really a meaningful thing to do, but which is presently taken as an assignment to the global variable named "". Also, since we have a local option -D (as in lua -D foo or lua -D foo=baz), I changed the assign() subroutine to accept an argument with no '=' at all. The resulting routine is, alas, somewhat longer.

static int assign (const char *arg) {		/* comment 1 */
  const char *eq;
  size_t lenvar;

  eq = strchr(arg, '=');			/* comment 3 */
  if (eq == NULL) {				/* comment 2 */
	/* no equal sign? define as "" */
	eq = "";
	lenvar = strlen(arg);
  } else if (eq == arg) {			/* comment 3 */
	fprintf(stderr, "lua: can't define \"{nothing}={val}\"\n");
	return (EXIT_FAILURE);
  } else {
	lenvar = eq - arg;
	++eq;
  }

  /* ok, set the value without clobbering args */
  lua_getglobals(L);			/* reference the global table */
  lua_pushlstring(L, arg, lenvar); 	/* push the key */
  lua_pushstring(L, eq);		/* push the value */
  lua_settable(L, -3);			/* set globals["x"]="value" */
  lua_pop(L, 1);			/* ditch the globals ref */
  return EXIT_SUCCESS;
}

Comments:

1) changed type of arg to const char *.

2) local style is to only assign during a declaration if the variable's value is immutable. [i.e., const char * const eq = ... would be ok]. But since eq is changed (see comment 3), I broke up the declaration.

3) this catches the case where there's no '=' in the input.

4) this catches the case where there's no variable to the left of the '='.

--Terry
tmm@mcci.com	tel: +1-607-277-1029	fax: +1-607-277-6844	www.mcci.com