Commit Diff


commit - bc298316465678d2483ba33625c5b4c6a70c8066
commit + acf1403a4bf484e8fdddfbba698733bfcac8266d
blob - 3207aba3d37bbaa7e4064702c8554c2e3bf328c2
blob + db86711edf514c92a2c1cb54a87131189de1307b
--- np.y
+++ np.y
@@ -96,7 +96,7 @@ typedef struct {
 %token	<v.str>		STRING SYMBOL
 %token	<v.num>		NUMBER
 
-%type	<v.op>		cast cexpr check expr funcall
+%type	<v.op>		cast cexpr check expr faccess funcall
 %type	<v.op>		literal var varref
 
 %type	<v.proc>	procname
@@ -157,15 +157,19 @@ literal	: STRING		{ $$ = op_lit_str($1); }
  * `expr '=' '=' expr` is ambiguous.  furthermore, we're not
  * interested in checking all the possibilities here.
  */
-cexpr	: literal | varref | funcall ;
+cexpr	: literal | varref | funcall | faccess ;
 check	: cexpr '=' '=' cexpr	{ $$ = op_cmp_eq($1, $4); }	;
 
-expr	: literal | funcall | varref | check | cast ;
+expr	: literal | funcall | varref | check | cast | faccess ;
 
 cast	: expr ':' U8	{ $$ = op_cast($1, V_U8); }
 	| expr ':' U16	{ $$ = op_cast($1, V_U16); }
 	| expr ':' U32	{ $$ = op_cast($1, V_U32); }
 	| expr ':' STR	{ $$ = op_cast($1, V_STR); }
+	;
+
+faccess	: varref '.' SYMBOL	{ $$ = op_faccess($1, $3); }
+	| faccess '.' SYMBOL	{ $$ = op_faccess($1, $3); }
 	;
 
 procname: SYMBOL {
blob - b63dac1d8755d3325c9ac524e93162f91b617940
blob + 42ce6187525e3d9564109b91e41b37c6585675d4
--- script.c
+++ script.c
@@ -399,6 +399,18 @@ op_cast(struct op *expr, int totype)
 	op = newop(OP_CAST);
 	op->v.cast.expr = expr;
 	op->v.cast.totype = totype;
+
+	return op;
+}
+
+struct op *
+op_faccess(struct op *expr, char *field)
+{
+	struct op *op;
+
+	op = newop(OP_FACCESS);
+	op->v.faccess.expr = expr;
+	op->v.faccess.field = field;
 
 	return op;
 }
@@ -538,6 +550,28 @@ val_cast(struct value *a, int totype)
 	}
 
 #undef NUMCAST
+}
+
+int
+val_faccess(struct value *a, const char *field, struct value *ret)
+{
+	switch (a->type) {
+	case V_QID:
+		/* TODO: add path.  needs uint64_t values thought! */
+		if (!strcmp(field, "vers")) {
+			ret->type = V_U32;
+			memcpy(&ret->v.u32, a->v.qid+1, 4);
+		} else if (!strcmp(field, "type")) {
+			ret->type = V_U8;
+			ret->v.u8 = *a->v.qid;
+		} else
+			return EVAL_ERR;
+		break;
+	default:
+		return EVAL_ERR;
+	}
+
+	return EVAL_OK;
 }
 
 void
@@ -588,6 +622,10 @@ pp_op(struct op *op)
 		printf(" == ");
 		pp_op(op->v.cmp_eq.b);
 		break;
+	case OP_FACCESS:
+		pp_op(op->v.faccess.expr);
+		printf(".%s", op->v.faccess.field);
+		break;
 	default:
 		printf(" ???[%d] ", op->type);
 	}
@@ -732,6 +770,16 @@ eval(struct op *op)
 
 		break;
 
+	case OP_FACCESS:
+		if ((ret = eval(op->v.faccess.expr)) != EVAL_OK)
+			return ret;
+		popv(&a);
+		if ((ret = val_faccess(&a, op->v.faccess.field, &b))
+		    != EVAL_OK)
+			return ret;
+		pushv(&b);
+		break;
+
 	default:
 		fprintf(stderr, "invalid op, aborting.\n");
 		abort();
blob - 8c76ca4a7701c4b9bda43bdb8bce8c5dea410446
blob + 17f3b1a715d44b40d02f3bd814df9e1dd81ab96d
--- script.h
+++ script.h
@@ -59,6 +59,7 @@ enum {
 	OP_VAR,
 	OP_CAST,
 	OP_CMP_EQ,
+	OP_FACCESS,
 };
 
 struct proc;
@@ -87,6 +88,10 @@ struct op {
 			struct op	*a;
 			struct op	*b;
 		} cmp_eq;
+		struct {
+			struct op	*expr;
+			char		*field;
+		} faccess;
 	} v;
 };
 
@@ -155,12 +160,14 @@ 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_cast(struct op *, int);
+struct op	*op_faccess(struct op *, char *);
 
 void		 ppf_val(FILE *, struct value *);
 void		 pp_val(struct value *);
 int		 val_trueish(struct value *);
 int		 val_eq(struct value *, struct value *);
 int		 val_cast(struct value *, int);
+int		 val_faccess(struct value *, const char *, struct value *);
 void		 pp_op(struct op *);
 void		 pp_block(struct op *);
 int		 eval(struct op *);