das@earvax.UUCP (Dave Steffens) (08/11/86)
Index: src/bin/expr.y Several months ago I posted in net.bugs.4bsd a fix to expr(1) so that it would handle negative arguments correctly. In the discussion that followed it was pointed out that my fix fails to correctly handle the case: expr --5 + 1 I feel that this should be an error since "--5" is not a legal number. If the unary minus operator is what is wanted, the correct syntax is: expr - -5 + 1 since the manual page states each token must be a separate argument. Well, the original expr(1) doesn't have unary minus so I just ignored this. But recently I have had some need for unary minus so I decided to add it. I have also added a test which makes "--5" an error under arithmetic operators and a string under compare operators so that: expr --5 \<= --4 correctly gives 0. In my original fix this gave 1 because both args were treated as numbers and "atol()" returns 0 when passed illegal strings. One possible disadvantage of this modification is that several undocumented operators ("match", "length", "index" and "substr") must be deleted in order to pass yacc without reduce/reduce conflicts. However, in the discussion someone said these operators have already been removed from SYSV source, probably because they were found to cause trouble in string matches. In the diffs that follow I have used the original 4.2bsd version of expr.y so my negative argument fix is included for those who might have missed it. 1c1,10 < /* Yacc productions for "expr" command: */ --- > /* > * Yacc productions for "expr" command > * > * 4.2bsd version > * Modified to handle negative numbers as arguments, DAS JUN-86 > * Modified to avoid "illegal pointer op" messages, DAS JUN-86 > * Added unary minus, DAS AUG-86 > * Deleted code for undocumented operators, DAS AUG-86 > * Improved definition of and testing for legal numbers, DAS AUG-86 > */ 3,4c12,14 < %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ < %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH --- > %union { > char *s; > } 5a16,20 > %type <s> expr > %token <s> A_STRING > > %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ NOARG > 11a27 > %right UMINUS 13,15d28 < %left MATCH < %left SUBSTR < %left LENGTH INDEX 40a54 > | SUBT expr %prec UMINUS = { $$ = arith(SUBT, "0", $2); } 42,45d55 < | MATCH expr expr = { $$ = match($2, $3); } < | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); } < | LENGTH expr = { $$ = length($2); } < | INDEX expr expr = { $$ = index($2, $3); } 48a59 > 71,72c82,83 < "=", "==", "<", "<=", ">", ">=", "!=", < "match", "substr", "length", "index", "\0" }; --- > "=", "==", "<", "<=", ">", ">=", "!=", "\0" }; > 74,75c85,86 < EQ, EQ, LT, LEQ, GT, GEQ, NEQ, < MATCH, SUBSTR, LENGTH, INDEX }; --- > EQ, EQ, LT, LEQ, GT, GEQ, NEQ, }; > 90c101 < yylval = p; --- > yylval.s = p; 93a105,106 > #define ISNUMBER(x) (ematch(x, "-*[0-9]*$") && !ematch(x, "--")) > 97c110 < if(ematch(r1, "-*[0-9]*$") && ematch(r2, "[0-9]*$")) --- > if (ISNUMBER(r1) && ISNUMBER(r2)) 116c129 < if(!(ematch(r1, "[0-9]*$") && ematch(r2, "[0-9]*$"))) --- > if (!ISNUMBER(r1) || !ISNUMBER(r2)) 131a145 > 162,201d175 < char *substr(v, s, w) char *v, *s, *w; { < ... code deleted ... < } < < char *length(s) register char *s; { < ... code deleted ... < } < < char *index(s, t) char *s, *t; { < ... code deleted ... < } < -- {harvard,mit-eddie,think}!eplunix!earvax!das David Allan Steffens 243 Charles St., Boston, MA 02114 Eaton-Peabody Laboratory (617) 523-7900 x2748 Mass. Eye & Ear Infirmary