Commit Diff


commit - 769047e6df99437f3dce8ba0e3da85a93cccd512
commit + a1911b2651392b42ee2454ec22366777f4ff0017
blob - e856da804353a10ea38daeea0e7396e071ecbc58
blob + 3b22364359c6f834886ffda7912b580339df0524
--- np.y
+++ np.y
@@ -163,7 +163,9 @@ literal	: STRING		{ $$ = op_lit_str($1); }
  * interested in checking all the possibilities here.
  */
 cexpr	: literal | varref | funcall | faccess ;
-check	: cexpr '=' '=' cexpr	{ $$ = op_cmp_eq($1, $4); }	;
+check	: cexpr '=' '=' cexpr	{ $$ = op_cmp_eq($1, $4); }
+	| cexpr '<' '=' cexpr	{ $$ = op_cmp_leq($1, $4); }
+	;
 
 expr	: literal | funcall | varref | check | cast | faccess | vargs ;
 
blob - d2d2f771c888629ea4e01ae4d9192cd199a28f26
blob + 8b480c2ff8bd568c4adadc410eed846e8f7696d2
--- script.c
+++ script.c
@@ -428,8 +428,9 @@ free_op(struct op *op)
 		free_op_rec(op->v.cast.expr);
 		break;
 	case OP_CMP_EQ:
-		free_op_rec(op->v.cmp_eq.a);
-		free_op_rec(op->v.cmp_eq.b);
+	case OP_CMP_LEQ:
+		free_op_rec(op->v.bin_cmp.a);
+		free_op_rec(op->v.bin_cmp.b);
 		break;
 	case OP_FACCESS:
 		free_op_rec(op->v.faccess.expr);
@@ -517,13 +518,25 @@ op_cmp_eq(struct op *a, struct op *b)
 	struct op *op;
 
 	op = newop(OP_CMP_EQ);
-	op->v.cmp_eq.a = a;
-	op->v.cmp_eq.b = b;
+	op->v.bin_cmp.a = a;
+	op->v.bin_cmp.b = b;
 
 	return op;
 }
 
 struct op *
+op_cmp_leq(struct op *a, struct op *b)
+{
+	struct op *op;
+
+	op = newop(OP_CMP_LEQ);
+	op->v.bin_cmp.a = a;
+	op->v.bin_cmp.b = b;
+
+	return op;
+}
+
+struct op *
 op_cast(struct op *expr, int totype)
 {
 	struct op *op;
@@ -677,7 +690,15 @@ val_eq(struct value *a, struct value *b)
 	case V_SYM:
 		return !strcmp(a->v.str, b->v.str);
 	}
+
+	return 0;
+}
 
+int
+val_leq(struct value *a, struct value *b)
+{
+	if (val_isnum(a) && val_isnum(b))
+		return val_tonum(a) <= val_tonum(b);
 	return 0;
 }
 
@@ -879,10 +900,15 @@ pp_op(struct op *op)
 		}
 		break;
 	case OP_CMP_EQ:
-		pp_op(op->v.cmp_eq.a);
+		pp_op(op->v.bin_cmp.a);
 		printf(" == ");
-		pp_op(op->v.cmp_eq.b);
+		pp_op(op->v.bin_cmp.b);
 		break;
+	case OP_CMP_LEQ:
+		pp_op(op->v.bin_cmp.a);
+		printf(" <= ");
+		pp_op(op->v.bin_cmp.b);
+		break;
 	case OP_FACCESS:
 		pp_op(op->v.faccess.expr);
 		printf(".%s", op->v.faccess.field);
@@ -1052,9 +1078,9 @@ eval(struct op *op)
 		break;
 
 	case OP_CMP_EQ:
-		if ((ret = eval(op->v.cmp_eq.a)) != EVAL_OK)
+		if ((ret = eval(op->v.bin_cmp.a)) != EVAL_OK)
 			return ret;
-		if ((ret = eval(op->v.cmp_eq.b)) != EVAL_OK)
+		if ((ret = eval(op->v.bin_cmp.b)) != EVAL_OK)
 			return ret;
 
 		popv(&b);
@@ -1062,6 +1088,17 @@ eval(struct op *op)
 		pushbool(val_eq(&a, &b));
 		break;
 
+	case OP_CMP_LEQ:
+		if ((ret = eval(op->v.bin_cmp.a)) != EVAL_OK)
+			return ret;
+		if ((ret = eval(op->v.bin_cmp.b)) != EVAL_OK)
+			return ret;
+
+		popv(&b);
+		popv(&a);
+		pushbool(val_leq(&a, &b));
+		break;
+
 	case OP_FACCESS:
 		if ((ret = eval(op->v.faccess.expr)) != EVAL_OK)
 			return ret;
blob - 8e094a0a1f2b051994a39fe747d5803f68d7bb85
blob + f7b6a07ae2b5f8ecc35bea64130cf0b6af2af2c0
--- script.h
+++ script.h
@@ -69,6 +69,7 @@ enum {
 	OP_VAR,
 	OP_CAST,
 	OP_CMP_EQ,
+	OP_CMP_LEQ,
 	OP_FACCESS,
 	OP_SFAIL,
 	OP_VARGS,
@@ -99,7 +100,7 @@ struct op {
 		struct {
 			struct op	*a;
 			struct op	*b;
-		} cmp_eq;
+		} bin_cmp;
 		struct {
 			struct op	*expr;
 			char		*field;
@@ -177,6 +178,7 @@ struct op	*op_var(char *);
 struct op	*op_lit_str(char *);
 struct op	*op_lit_num(uint64_t);
 struct op	*op_cmp_eq(struct op *, struct op *);
+struct op	*op_cmp_leq(struct op *, struct op *);
 struct op	*op_cast(struct op *, int);
 struct op	*op_faccess(struct op *, char *);
 struct op	*op_sfail(struct op *, char *);
@@ -190,6 +192,7 @@ int		 val_trueish(struct value *);
 int		 val_isnum(struct value *);
 int64_t		 val_tonum(struct value *);
 int		 val_eq(struct value *, struct value *);
+int		 val_leq(struct value *, struct value *);
 int		 val_cast(struct value *, int);
 int		 val_faccess(struct value *, const char *, struct value *);
 void		 pp_op(struct op *);