Jon Nelson <[EMAIL PROTECTED]> writes:
> I don't think I could have voiced it better myself. Mitch is absolutely
> right here when he says that empty ("") is *not* the same as
> non-existant. It may not make perfect sense for SENDER, but for other
> variables it may -- indeed, the mere presence (regardless of content) of
> the variable is enough for some programs.
>
> Please, Sam, reconsider this code that seems to me to:
>
> a) /not/ operate on the principle of least surprise (thanks, "Courier
> User").
> b) /not/ follow common convention
> c) unintuitive
> d) it breaks a bunch of software
>
> Adding the 'unset' directive would allow those people that rely on the
> current (broken, IMO) behavior to continue "unsetting" variables.
Attached is a patch to maildrop (in the 0.44.2.20031219 release of
Courier) which implements the following features:
1. VAR=""
No longer unsets the variable, but simply sets it to
an empty string, as does every other variable-setting
language that I know of.
2. unset VAR
A new directive that completely removes the variable.
I've done a small amount of testing, and it seems OK, but please do your
own testing, as well.
*** maildrop/lexer.C.save Wed Jan 14 09:31:21 2004
--- maildrop/lexer.C Wed Jan 14 09:32:29 2004
***************
*** 384,389 ****
--- 384,391 ----
t.Type(Token::importtoken);
else if (pattern == "-") // Hack
t.Type(Token::minus);
+ else if (pattern == "unset")
+ t.Type(Token::unset);
else
t.Type(Token::qstring);
return;
*** maildrop/recipenode.C.save Wed Jan 14 09:27:59 2004
--- maildrop/recipenode.C Wed Jan 14 09:49:54 2004
***************
*** 1066,1071 ****
--- 1066,1089 ----
b.append( (unsigned long)t );
}
break;
+ case unset:
+ if (!firstChild)
+ throw "Internal error in unset statement.";
+ firstChild->Evaluate(r, b);
+ {
+ Buffer s;
+
+ if (VerboseLevel() > 3)
+ {
+ s="unset ";
+ s += b;
+ s += '\0';
+ r.errmsg(*this, s);
+ }
+
+ UnsetVar(b);
+ }
+ break;
}
}
*** maildrop/recipenode.h.save Wed Jan 14 09:27:46 2004
--- maildrop/recipenode.h Wed Jan 14 09:48:48 2004
***************
*** 116,122 ****
gdbmfetch,
gdbmstore,
timetoken,
! importtoken
} nodeType;
RecipeNode(RecipeNodeType);
--- 116,123 ----
gdbmfetch,
gdbmstore,
timetoken,
! importtoken,
! unset
} nodeType;
RecipeNode(RecipeNodeType);
*** maildrop/recipeparse.C.save Wed Jan 14 09:28:08 2004
--- maildrop/recipeparse.C Wed Jan 14 09:46:47 2004
***************
*** 235,240 ****
--- 235,248 ----
throw "Syntax error.";
lex->token(cur_tok);
return (n);
+ case Token::unset:
+ lex->token(cur_tok);
+ n=alloc(RecipeNode::unset);
+ n->AppendSibling( ParseExpr());
+ if (cur_tok.Type() != Token::semicolon)
+ throw "Syntax error.";
+ lex->token(cur_tok);
+ return (n);
default:
break;
}
*** maildrop/token.C.save Wed Jan 14 09:32:48 2004
--- maildrop/token.C Wed Jan 14 09:35:07 2004
***************
*** 67,73 ****
"gdbmfetch",
"gdbmstore",
"time",
! "import"
} ;
static Buffer namebuf;
--- 67,74 ----
"gdbmfetch",
"gdbmstore",
"time",
! "import",
! "unset"
} ;
static Buffer namebuf;
*** maildrop/token.h.save Wed Jan 14 09:32:53 2004
--- maildrop/token.h Wed Jan 14 09:46:33 2004
***************
*** 84,89 ****
--- 84,90 ----
gdbmstore,
timetoken,
importtoken,
+ unset,
};
private:
tokentype type;
*** maildrop/varlist.C.save Wed Jan 14 09:15:22 2004
--- maildrop/varlist.C Wed Jan 14 09:22:41 2004
***************
*** 16,21 ****
--- 16,52 ----
static Variable *varlist[101];
+ void UnsetVar(const Buffer &var)
+ {
+ int varlen=var.Length();
+ unsigned n=0;
+ int i;
+ const char *p=var;
+ for (i=varlen; i; --i)
+ n = (n << 1) ^ (unsigned char)*p++;
+
+ if (var.Length() == 7 &&
+ strncmp( (const char *)var, "VERBOSE", 7) == 0)
+ {
+ maildrop.verbose_level=0;
+ }
+
+ n %= sizeof(varlist)/sizeof(varlist[0]);
+
+ Variable **v;
+
+ for (v= &varlist[n]; *v; v= &(*v)->next)
+ if ( (*v)->name == var )
+ {
+ Variable *vv= (*v);
+
+ (*v)= vv->next;
+ delete vv;
+ break;
+ }
+ return;
+ }
+
void SetVar(const Buffer &var, const Buffer &value)
{
int varlen=var.Length();
***************
*** 34,55 ****
}
n %= sizeof(varlist)/sizeof(varlist[0]);
-
- if (value.Length() == 0) // Delete variable
- {
- Variable **v;
-
- for (v= &varlist[n]; *v; v= &(*v)->next)
- if ( (*v)->name == var )
- {
- Variable *vv= (*v);
-
- (*v)= vv->next;
- delete vv;
- break;
- }
- return;
- }
Variable *v;
--- 65,70 ----
*** maildrop/varlist.h.save Wed Jan 14 09:23:42 2004
--- maildrop/varlist.h Wed Jan 14 09:24:05 2004
***************
*** 9,14 ****
--- 9,15 ----
class Buffer;
+ void UnsetVar(const Buffer &);
void SetVar(const Buffer &, const Buffer &);
const Buffer *GetVar(const Buffer &);
const char *GetVarStr(const Buffer &);
--
Courier User
[EMAIL PROTECTED]