Home | History | Annotate | Line # | Download | only in expr
expr.y revision 1.14.2.1
      1       1.1  cgd %{
      2       1.1  cgd /* Written by Pace Willisson (pace (at) blitz.com)
      3      1.11  jtc  * and placed in the public domain.
      4       1.2  cgd  *
      5      1.11  jtc  * Largely rewritten by J.T. Conklin (jtc (at) wimsey.com)
      6      1.11  jtc  *
      7      1.12  jtc  * $Id : /b/source/CVS/src/bin/expr/expr.y,v 1.11 1993/08/17 16:01:23 jtc Exp $
      8       1.1  cgd  */
      9      1.12  jtc 
     10       1.1  cgd #include <stdio.h>
     11       1.4  cgd #include <stdlib.h>
     12       1.4  cgd #include <string.h>
     13      1.12  jtc #include <locale.h>
     14       1.1  cgd #include <ctype.h>
     15      1.11  jtc #include <err.h>
     16       1.5  cgd 
     17       1.4  cgd enum valtype {
     18       1.4  cgd 	integer, string
     19       1.4  cgd } ;
     20       1.5  cgd 
     21       1.1  cgd struct val {
     22       1.4  cgd 	enum valtype type;
     23       1.4  cgd 	union {
     24       1.4  cgd 		char *s;
     25       1.4  cgd 		int   i;
     26       1.4  cgd 	} u;
     27       1.5  cgd } ;
     28       1.1  cgd 
     29       1.1  cgd struct val *result;
     30       1.1  cgd struct val *op_or ();
     31       1.1  cgd struct val *op_and ();
     32       1.1  cgd struct val *op_eq ();
     33       1.1  cgd struct val *op_gt ();
     34       1.1  cgd struct val *op_lt ();
     35       1.1  cgd struct val *op_ge ();
     36       1.1  cgd struct val *op_le ();
     37       1.1  cgd struct val *op_ne ();
     38       1.1  cgd struct val *op_plus ();
     39       1.1  cgd struct val *op_minus ();
     40       1.1  cgd struct val *op_times ();
     41       1.1  cgd struct val *op_div ();
     42       1.1  cgd struct val *op_rem ();
     43       1.1  cgd struct val *op_colon ();
     44       1.1  cgd 
     45       1.1  cgd char **av;
     46       1.1  cgd %}
     47       1.1  cgd 
     48       1.1  cgd %union
     49       1.1  cgd {
     50       1.1  cgd 	struct val *val;
     51       1.1  cgd }
     52       1.1  cgd 
     53       1.1  cgd %left <val> '|'
     54       1.1  cgd %left <val> '&'
     55       1.1  cgd %left <val> '=' '>' '<' GE LE NE
     56       1.1  cgd %left <val> '+' '-'
     57       1.1  cgd %left <val> '*' '/' '%'
     58       1.1  cgd %left <val> ':'
     59       1.1  cgd 
     60       1.1  cgd %token <val> TOKEN
     61       1.1  cgd %type <val> start expr
     62       1.1  cgd 
     63       1.1  cgd %%
     64       1.1  cgd 
     65       1.1  cgd start: expr { result = $$; }
     66       1.1  cgd 
     67       1.1  cgd expr:	TOKEN
     68       1.1  cgd 	| '(' expr ')' { $$ = $2; }
     69       1.1  cgd 	| expr '|' expr { $$ = op_or ($1, $3); }
     70       1.1  cgd 	| expr '&' expr { $$ = op_and ($1, $3); }
     71       1.1  cgd 	| expr '=' expr { $$ = op_eq ($1, $3); }
     72       1.1  cgd 	| expr '>' expr { $$ = op_gt ($1, $3); }
     73       1.1  cgd 	| expr '<' expr { $$ = op_lt ($1, $3); }
     74       1.1  cgd 	| expr GE expr  { $$ = op_ge ($1, $3); }
     75       1.1  cgd 	| expr LE expr  { $$ = op_le ($1, $3); }
     76       1.1  cgd 	| expr NE expr  { $$ = op_ne ($1, $3); }
     77       1.1  cgd 	| expr '+' expr { $$ = op_plus ($1, $3); }
     78       1.1  cgd 	| expr '-' expr { $$ = op_minus ($1, $3); }
     79       1.1  cgd 	| expr '*' expr { $$ = op_times ($1, $3); }
     80       1.1  cgd 	| expr '/' expr { $$ = op_div ($1, $3); }
     81       1.1  cgd 	| expr '%' expr { $$ = op_rem ($1, $3); }
     82       1.1  cgd 	| expr ':' expr { $$ = op_colon ($1, $3); }
     83       1.1  cgd 	;
     84       1.1  cgd 
     85       1.1  cgd 
     86       1.1  cgd %%
     87       1.1  cgd 
     88       1.1  cgd struct val *
     89       1.4  cgd make_integer (i)
     90       1.4  cgd int i;
     91       1.4  cgd {
     92       1.4  cgd 	struct val *vp;
     93       1.4  cgd 
     94       1.5  cgd 	vp = (struct val *) malloc (sizeof (*vp));
     95       1.4  cgd 	if (vp == NULL) {
     96      1.11  jtc 		err (2, NULL);
     97       1.4  cgd 	}
     98       1.4  cgd 
     99       1.4  cgd 	vp->type = integer;
    100       1.4  cgd 	vp->u.i  = i;
    101       1.4  cgd 	return vp;
    102       1.4  cgd }
    103       1.4  cgd 
    104       1.4  cgd struct val *
    105       1.4  cgd make_str (s)
    106       1.4  cgd char *s;
    107       1.1  cgd {
    108       1.1  cgd 	struct val *vp;
    109       1.1  cgd 
    110       1.5  cgd 	vp = (struct val *) malloc (sizeof (*vp));
    111       1.4  cgd 	if (vp == NULL || ((vp->u.s = strdup (s)) == NULL)) {
    112      1.11  jtc 		err (2, NULL);
    113       1.1  cgd 	}
    114       1.1  cgd 
    115       1.4  cgd 	vp->type = string;
    116       1.4  cgd 	return vp;
    117       1.4  cgd }
    118       1.4  cgd 
    119       1.4  cgd 
    120       1.4  cgd void
    121       1.4  cgd free_value (vp)
    122       1.4  cgd struct val *vp;
    123       1.4  cgd {
    124       1.4  cgd 	if (vp->type == string)
    125       1.4  cgd 		free (vp->u.s);
    126      1.14  jtc 	free (vp);
    127       1.4  cgd }
    128       1.4  cgd 
    129       1.1  cgd 
    130       1.4  cgd int
    131       1.4  cgd to_integer (vp)
    132       1.4  cgd struct val *vp;
    133       1.4  cgd {
    134       1.4  cgd 	char *s;
    135       1.4  cgd 	int neg;
    136       1.4  cgd 	int i;
    137       1.4  cgd 
    138       1.4  cgd 	if (vp->type == integer)
    139       1.4  cgd 		return 1;
    140       1.4  cgd 
    141       1.4  cgd 	s = vp->u.s;
    142       1.4  cgd 	i = 0;
    143       1.4  cgd 
    144       1.4  cgd 	neg = (*s == '-');
    145       1.4  cgd 	if (neg)
    146       1.4  cgd 		s++;
    147       1.4  cgd 
    148       1.4  cgd 	for (;*s; s++) {
    149       1.4  cgd 		if (!isdigit (*s))
    150       1.4  cgd 			return 0;
    151       1.4  cgd 
    152       1.4  cgd 		i *= 10;
    153       1.4  cgd 		i += *s - '0';
    154       1.1  cgd 	}
    155       1.1  cgd 
    156       1.4  cgd 	free (vp->u.s);
    157       1.4  cgd 	if (neg)
    158       1.4  cgd 		i *= -1;
    159       1.4  cgd 
    160       1.4  cgd 	vp->type = integer;
    161       1.4  cgd 	vp->u.i  = i;
    162       1.4  cgd 	return 1;
    163       1.1  cgd }
    164       1.1  cgd 
    165       1.4  cgd void
    166       1.4  cgd to_string (vp)
    167       1.4  cgd struct val *vp;
    168       1.1  cgd {
    169       1.4  cgd 	char *tmp;
    170       1.4  cgd 
    171       1.4  cgd 	if (vp->type == string)
    172       1.4  cgd 		return;
    173       1.4  cgd 
    174       1.4  cgd 	tmp = malloc (25);
    175       1.4  cgd 	if (tmp == NULL) {
    176      1.11  jtc 		err (2, NULL);
    177       1.4  cgd 	}
    178       1.4  cgd 
    179       1.4  cgd 	sprintf (tmp, "%d", vp->u.i);
    180       1.4  cgd 	vp->type = string;
    181       1.4  cgd 	vp->u.s  = tmp;
    182       1.4  cgd }
    183       1.4  cgd 
    184       1.1  cgd 
    185       1.4  cgd int
    186       1.4  cgd isstring (vp)
    187       1.4  cgd struct val *vp;
    188       1.4  cgd {
    189       1.4  cgd 	return (vp->type == string);
    190       1.1  cgd }
    191       1.1  cgd 
    192       1.4  cgd 
    193       1.1  cgd int
    194       1.1  cgd yylex ()
    195       1.1  cgd {
    196       1.1  cgd 	struct val *vp;
    197       1.1  cgd 	char *p;
    198       1.1  cgd 
    199       1.1  cgd 	if (*av == NULL)
    200       1.1  cgd 		return (0);
    201       1.1  cgd 
    202       1.1  cgd 	p = *av++;
    203       1.1  cgd 
    204       1.1  cgd 	if (strlen (p) == 1) {
    205       1.4  cgd 		if (strchr ("|&=<>+-*/%:()", *p))
    206       1.1  cgd 			return (*p);
    207       1.1  cgd 	} else if (strlen (p) == 2 && p[1] == '=') {
    208       1.1  cgd 		switch (*p) {
    209       1.1  cgd 		case '>': return (GE);
    210       1.1  cgd 		case '<': return (LE);
    211       1.1  cgd 		case '!': return (NE);
    212       1.1  cgd 		}
    213       1.1  cgd 	}
    214       1.1  cgd 
    215       1.4  cgd 	yylval.val = make_str (p);
    216       1.1  cgd 	return (TOKEN);
    217       1.1  cgd }
    218       1.1  cgd 
    219       1.1  cgd int
    220       1.1  cgd is_zero_or_null (vp)
    221       1.1  cgd struct val *vp;
    222       1.1  cgd {
    223       1.4  cgd 	if (vp->type == integer) {
    224       1.5  cgd 		return (vp->u.i == 0);
    225       1.4  cgd 	} else {
    226       1.9  jtc 		return (*vp->u.s == 0 || (to_integer (vp) && vp->u.i == 0));
    227       1.4  cgd 	}
    228       1.5  cgd 	/* NOTREACHED */
    229       1.1  cgd }
    230       1.1  cgd 
    231       1.1  cgd void
    232       1.1  cgd main (argc, argv)
    233       1.1  cgd int argc;
    234       1.1  cgd char **argv;
    235       1.1  cgd {
    236      1.12  jtc 	setlocale (LC_ALL, "");
    237      1.12  jtc 
    238       1.1  cgd 	av = argv + 1;
    239       1.1  cgd 
    240       1.1  cgd 	yyparse ();
    241       1.1  cgd 
    242       1.4  cgd 	if (result->type == integer)
    243       1.4  cgd 		printf ("%d\n", result->u.i);
    244       1.1  cgd 	else
    245       1.4  cgd 		printf ("%s\n", result->u.s);
    246       1.1  cgd 
    247      1.12  jtc 	exit (is_zero_or_null (result));
    248       1.1  cgd }
    249       1.1  cgd 
    250       1.1  cgd int
    251       1.1  cgd yyerror (s)
    252       1.1  cgd char *s;
    253       1.1  cgd {
    254      1.11  jtc 	errx (2, "syntax error");
    255       1.1  cgd }
    256       1.1  cgd 
    257       1.1  cgd 
    258       1.1  cgd struct val *
    259       1.1  cgd op_or (a, b)
    260       1.1  cgd struct val *a, *b;
    261       1.1  cgd {
    262       1.4  cgd 	if (is_zero_or_null (a)) {
    263       1.4  cgd 		free_value (a);
    264       1.1  cgd 		return (b);
    265       1.4  cgd 	} else {
    266       1.4  cgd 		free_value (b);
    267       1.1  cgd 		return (a);
    268       1.4  cgd 	}
    269       1.1  cgd }
    270       1.1  cgd 
    271       1.1  cgd struct val *
    272       1.1  cgd op_and (a, b)
    273       1.1  cgd struct val *a, *b;
    274       1.1  cgd {
    275       1.4  cgd 	if (is_zero_or_null (a) || is_zero_or_null (b)) {
    276       1.4  cgd 		free_value (a);
    277       1.4  cgd 		free_value (b);
    278       1.1  cgd 		return (make_integer (0));
    279       1.4  cgd 	} else {
    280       1.4  cgd 		free_value (b);
    281       1.1  cgd 		return (a);
    282       1.4  cgd 	}
    283       1.1  cgd }
    284       1.1  cgd 
    285       1.1  cgd struct val *
    286       1.1  cgd op_eq (a, b)
    287       1.1  cgd struct val *a, *b;
    288       1.1  cgd {
    289       1.4  cgd 	struct val *r;
    290       1.4  cgd 
    291       1.4  cgd 	if (isstring (a) || isstring (b)) {
    292       1.4  cgd 		to_string (a);
    293       1.4  cgd 		to_string (b);
    294      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) == 0);
    295       1.4  cgd 	} else {
    296       1.4  cgd 		r = make_integer (a->u.i == b->u.i);
    297       1.4  cgd 	}
    298       1.4  cgd 
    299       1.4  cgd 	free_value (a);
    300       1.4  cgd 	free_value (b);
    301       1.4  cgd 	return r;
    302       1.1  cgd }
    303       1.1  cgd 
    304       1.1  cgd struct val *
    305       1.1  cgd op_gt (a, b)
    306       1.1  cgd struct val *a, *b;
    307       1.1  cgd {
    308       1.4  cgd 	struct val *r;
    309       1.4  cgd 
    310       1.4  cgd 	if (isstring (a) || isstring (b)) {
    311       1.4  cgd 		to_string (a);
    312       1.4  cgd 		to_string (b);
    313      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) > 0);
    314       1.4  cgd 	} else {
    315       1.4  cgd 		r= make_integer (a->u.i > b->u.i);
    316       1.4  cgd 	}
    317       1.4  cgd 
    318       1.4  cgd 	free_value (a);
    319       1.4  cgd 	free_value (b);
    320       1.4  cgd 	return r;
    321       1.1  cgd }
    322       1.1  cgd 
    323       1.1  cgd struct val *
    324       1.1  cgd op_lt (a, b)
    325       1.1  cgd struct val *a, *b;
    326       1.1  cgd {
    327       1.4  cgd 	struct val *r;
    328       1.4  cgd 
    329       1.4  cgd 	if (isstring (a) || isstring (b)) {
    330       1.4  cgd 		to_string (a);
    331       1.4  cgd 		to_string (b);
    332      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) < 0);
    333       1.4  cgd 	} else {
    334       1.4  cgd 		r = make_integer (a->u.i < b->u.i);
    335       1.4  cgd 	}
    336       1.4  cgd 
    337       1.4  cgd 	free_value (a);
    338       1.4  cgd 	free_value (b);
    339       1.4  cgd 	return r;
    340       1.1  cgd }
    341       1.1  cgd 
    342       1.1  cgd struct val *
    343       1.1  cgd op_ge (a, b)
    344       1.1  cgd struct val *a, *b;
    345       1.1  cgd {
    346       1.4  cgd 	struct val *r;
    347       1.4  cgd 
    348       1.4  cgd 	if (isstring (a) || isstring (b)) {
    349       1.4  cgd 		to_string (a);
    350       1.4  cgd 		to_string (b);
    351      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) >= 0);
    352       1.4  cgd 	} else {
    353       1.4  cgd 		r = make_integer (a->u.i >= b->u.i);
    354       1.4  cgd 	}
    355       1.4  cgd 
    356       1.4  cgd 	free_value (a);
    357       1.4  cgd 	free_value (b);
    358       1.4  cgd 	return r;
    359       1.1  cgd }
    360       1.1  cgd 
    361       1.1  cgd struct val *
    362       1.1  cgd op_le (a, b)
    363       1.1  cgd struct val *a, *b;
    364       1.1  cgd {
    365       1.4  cgd 	struct val *r;
    366       1.4  cgd 
    367       1.4  cgd 	if (isstring (a) || isstring (b)) {
    368       1.4  cgd 		to_string (a);
    369       1.4  cgd 		to_string (b);
    370      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) <= 0);
    371       1.4  cgd 	} else {
    372       1.4  cgd 		r = make_integer (a->u.i <= b->u.i);
    373       1.4  cgd 	}
    374       1.4  cgd 
    375       1.4  cgd 	free_value (a);
    376       1.4  cgd 	free_value (b);
    377       1.4  cgd 	return r;
    378       1.1  cgd }
    379       1.1  cgd 
    380       1.1  cgd struct val *
    381       1.1  cgd op_ne (a, b)
    382       1.1  cgd struct val *a, *b;
    383       1.1  cgd {
    384       1.4  cgd 	struct val *r;
    385       1.4  cgd 
    386       1.4  cgd 	if (isstring (a) || isstring (b)) {
    387       1.4  cgd 		to_string (a);
    388       1.4  cgd 		to_string (b);
    389      1.10  jtc 		r = make_integer (strcoll (a->u.s, b->u.s) != 0);
    390       1.4  cgd 	} else {
    391       1.4  cgd 		r = make_integer (a->u.i != b->u.i);
    392       1.4  cgd 	}
    393       1.4  cgd 
    394       1.4  cgd 	free_value (a);
    395       1.4  cgd 	free_value (b);
    396       1.4  cgd 	return r;
    397       1.1  cgd }
    398       1.1  cgd 
    399       1.1  cgd struct val *
    400       1.1  cgd op_plus (a, b)
    401       1.1  cgd struct val *a, *b;
    402       1.1  cgd {
    403       1.4  cgd 	struct val *r;
    404       1.4  cgd 
    405       1.4  cgd 	if (!to_integer (a) || !to_integer (b)) {
    406      1.11  jtc 		errx (2, "non-numeric argument");
    407       1.4  cgd 	}
    408       1.1  cgd 
    409       1.4  cgd 	r = make_integer (a->u.i + b->u.i);
    410       1.4  cgd 	free_value (a);
    411       1.4  cgd 	free_value (b);
    412       1.4  cgd 	return r;
    413       1.1  cgd }
    414       1.1  cgd 
    415       1.1  cgd struct val *
    416       1.1  cgd op_minus (a, b)
    417       1.1  cgd struct val *a, *b;
    418       1.1  cgd {
    419       1.4  cgd 	struct val *r;
    420       1.4  cgd 
    421       1.4  cgd 	if (!to_integer (a) || !to_integer (b)) {
    422      1.11  jtc 		errx (2, "non-numeric argument");
    423       1.4  cgd 	}
    424       1.1  cgd 
    425       1.4  cgd 	r = make_integer (a->u.i - b->u.i);
    426       1.4  cgd 	free_value (a);
    427       1.4  cgd 	free_value (b);
    428       1.4  cgd 	return r;
    429       1.1  cgd }
    430       1.1  cgd 
    431       1.1  cgd struct val *
    432       1.1  cgd op_times (a, b)
    433       1.1  cgd struct val *a, *b;
    434       1.1  cgd {
    435       1.4  cgd 	struct val *r;
    436       1.1  cgd 
    437       1.4  cgd 	if (!to_integer (a) || !to_integer (b)) {
    438      1.11  jtc 		errx (2, "non-numeric argument");
    439       1.4  cgd 	}
    440       1.4  cgd 
    441       1.4  cgd 	r = make_integer (a->u.i * b->u.i);
    442       1.4  cgd 	free_value (a);
    443       1.4  cgd 	free_value (b);
    444       1.4  cgd 	return (r);
    445       1.1  cgd }
    446       1.1  cgd 
    447       1.1  cgd struct val *
    448       1.1  cgd op_div (a, b)
    449       1.1  cgd struct val *a, *b;
    450       1.1  cgd {
    451       1.4  cgd 	struct val *r;
    452       1.4  cgd 
    453       1.4  cgd 	if (!to_integer (a) || !to_integer (b)) {
    454      1.11  jtc 		errx (2, "non-numeric argument");
    455       1.4  cgd 	}
    456       1.4  cgd 
    457       1.4  cgd 	if (b->u.i == 0) {
    458      1.11  jtc 		errx (2, "division by zero");
    459       1.4  cgd 	}
    460       1.1  cgd 
    461       1.4  cgd 	r = make_integer (a->u.i / b->u.i);
    462       1.4  cgd 	free_value (a);
    463       1.4  cgd 	free_value (b);
    464       1.4  cgd 	return r;
    465       1.1  cgd }
    466       1.1  cgd 
    467       1.1  cgd struct val *
    468       1.1  cgd op_rem (a, b)
    469       1.1  cgd struct val *a, *b;
    470       1.1  cgd {
    471       1.4  cgd 	struct val *r;
    472       1.4  cgd 
    473       1.4  cgd 	if (!to_integer (a) || !to_integer (b)) {
    474      1.11  jtc 		errx (2, "non-numeric argument");
    475       1.4  cgd 	}
    476       1.4  cgd 
    477       1.4  cgd 	if (b->u.i == 0) {
    478      1.11  jtc 		errx (2, "division by zero");
    479       1.4  cgd 	}
    480       1.1  cgd 
    481       1.4  cgd 	r = make_integer (a->u.i % b->u.i);
    482       1.4  cgd 	free_value (a);
    483       1.4  cgd 	free_value (b);
    484       1.4  cgd 	return r;
    485       1.1  cgd }
    486       1.1  cgd 
    487       1.6  jtc #include <regex.h>
    488       1.1  cgd 
    489       1.1  cgd struct val *
    490       1.1  cgd op_colon (a, b)
    491       1.1  cgd struct val *a, *b;
    492       1.1  cgd {
    493       1.6  jtc 	regex_t rp;
    494      1.12  jtc 	regmatch_t rm[2];
    495       1.6  jtc 	char errbuf[256];
    496       1.6  jtc 	int eval;
    497       1.6  jtc 	struct val *v;
    498       1.6  jtc 
    499       1.7  jtc 	/* coerce to both arguments to strings */
    500       1.7  jtc 	to_string(a);
    501       1.7  jtc 	to_string(b);
    502       1.6  jtc 
    503       1.6  jtc 	/* compile regular expression */
    504      1.13  jtc 	if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
    505       1.6  jtc 		regerror (eval, &rp, errbuf, sizeof(errbuf));
    506      1.11  jtc 		errx (2, "%s", errbuf);
    507       1.6  jtc 	}
    508       1.6  jtc 
    509       1.6  jtc 	/* compare string against pattern */
    510      1.13  jtc 	/* remember that patterns are anchored to the beginning of the line */
    511      1.13  jtc 	if (regexec(&rp, a->u.s, 2, rm, 0) == 0 && rm[0].rm_so == 0) {
    512       1.6  jtc 		if (rm[1].rm_so >= 0) {
    513      1.11  jtc 			*(a->u.s + rm[1].rm_eo) = '\0';
    514       1.6  jtc 			v = make_str (a->u.s + rm[1].rm_so);
    515       1.1  cgd 
    516       1.1  cgd 		} else {
    517  1.14.2.1  cgd 			v = make_integer ((int)(rm[0].rm_eo - rm[0].rm_so));
    518       1.1  cgd 		}
    519       1.1  cgd 	} else {
    520      1.11  jtc 		if (rp.re_nsub == 0) {
    521      1.11  jtc 			v = make_integer (0);
    522      1.11  jtc 		} else {
    523      1.11  jtc 			v = make_str ("");
    524      1.11  jtc 		}
    525       1.1  cgd 	}
    526       1.6  jtc 
    527       1.6  jtc 	/* free arguments and pattern buffer */
    528       1.6  jtc 	free_value (a);
    529       1.6  jtc 	free_value (b);
    530       1.6  jtc 	regfree (&rp);
    531       1.5  cgd 
    532       1.6  jtc 	return v;
    533       1.1  cgd }
    534