static struct test *read_tests(void) { char *fname = NULL; FILE *fp; char line[BUFSIZ]; struct test *result = NULL, *t = NULL; int lc = 0; bool append_cmd = true; if (asprintf(&fname, "%s/tests/run.tests", abs_top_srcdir) < 0) die("asprintf fname"); if ((fp = fopen(fname, "r")) == NULL) die("fopen run.tests"); while (fgets(line, BUFSIZ, fp) != NULL) { lc += 1; char *s = skipws(line); if (*s == '#' || *s == '\0') continue; if (*s == ':') s += 1; char *eos = s + strlen(s) - 2; if (eos >= s && *eos == ':') { *eos++ = '\n'; *eos = '\0'; } if (looking_at(s, KW_TEST)) { if (ALLOC(t) < 0) die_oom(); list_append(result, t); append_cmd = true; s = token(s + strlen(KW_TEST), &(t->name)); s = inttok(s, &t->result); s = errtok(s, &t->errcode); } else if (looking_at(s, KW_PRINTS)) { s = skipws(s + strlen(KW_PRINTS)); t->out_present = looking_at(s, KW_SOMETHING); append_cmd = false; } else if (looking_at(s, KW_USE)) { if (t->module !=NULL) die("Can use at most one module in a test"); s = token(s + strlen(KW_USE), &(t->module)); } else { char **buf = append_cmd ? &(t->cmd) : &(t->out); if (*buf == NULL) { *buf = strdup(s); if (*buf == NULL) die_oom(); } else { if (REALLOC_N(*buf, strlen(*buf) + strlen(s) + 1) < 0) die_oom(); strcat(*buf, s); } } if (t->out != NULL) t->out_present = true; } free(fname); return result; }
/* Calculate the regexp that matches the labels if the trees that L can generate. We have some headache here because of the behavior of STORE: since STORE creates a tree with no label (a leaf, really), its key regexp should be "/", but only of there is no KEY or LABEL statement that fills in the label of the tree that STORE created. */ static struct regexp *lns_key_regexp(struct lens *l, struct value **exn) { static const struct string digits_string = { .ref = REF_MAX, .str = (char *) "[0-9]+/" }; static const struct string *const digits_pat = &digits_string; *exn = NULL; switch(l->tag) { case L_STORE: case L_DEL: case L_COUNTER: return NULL; case L_SEQ: return make_regexp_from_string(l->info, (struct string *) digits_pat); case L_KEY: return make_key_regexp(l->info, l->regexp->pattern->str); case L_LABEL: { struct regexp *r = make_regexp_literal(l->info, l->string->str); if (r == NULL) return NULL; if (REALLOC_N(r->pattern->str, strlen(r->pattern->str) + 2) == -1) { unref(r, regexp); return NULL; } strcat(r->pattern->str, "/"); return r; } case L_CONCAT: { struct regexp *k = NULL; for (int i=0; i < l->nchildren; i++) { struct regexp *r = lns_key_regexp(l->children[i], exn); if (*exn != NULL) { free_regexp(k); return NULL; } if (r != NULL) { if (k != NULL) { *exn = make_exn_value(ref(l->info), "More than one key"); unref(r, regexp); unref(k, regexp); return NULL; } else { k = r; } } } return k; } break; case L_UNION: { struct regexp *k = NULL; for (int i=0; i < l->nchildren; i++) { struct regexp *r = lns_key_regexp(l->children[i], exn); if (*exn != NULL) return NULL; if (r != NULL) { if (k == NULL) { k = r; } else { struct regexp *u = regexp_union(l->info, k, r); unref(k, regexp); unref(r, regexp); k = u; } } } return k; } break; case L_SUBTREE: return NULL; break; case L_STAR: case L_MAYBE: return lns_key_regexp(l->child, exn); default: assert(0); } return NULL; } void free_lens(struct lens *lens) { if (lens == NULL) return; assert(lens->ref == 0); unref(lens->info, info); unref(lens->ctype, regexp); unref(lens->atype, regexp); switch (lens->tag) { case L_DEL: unref(lens->regexp, regexp); unref(lens->string, string); break; case L_STORE: case L_KEY: unref(lens->regexp, regexp); break; case L_LABEL: case L_SEQ: case L_COUNTER: unref(lens->string, string); break; case L_SUBTREE: case L_STAR: case L_MAYBE: unref(lens->child, lens); break; case L_CONCAT: case L_UNION: for (int i=0; i < lens->nchildren; i++) unref(lens->children[i], lens); free(lens->children); break; default: assert(0); break; } free(lens); } void lens_release(struct lens *lens) { if (lens == NULL) return; regexp_release(lens->ctype); regexp_release(lens->atype); if (lens->tag == L_KEY || lens->tag == L_STORE) regexp_release(lens->regexp); if (lens->tag == L_SUBTREE || lens->tag == L_STAR || lens->tag == L_MAYBE) { lens_release(lens->child); } if (lens->tag == L_UNION || lens->tag == L_CONCAT) { for (int i=0; i < lens->nchildren; i++) { lens_release(lens->children[i]); } } }
static VALUE fntype_initialize(int argc, VALUE* argv, VALUE self) { FunctionType *fnInfo; ffi_status status; VALUE rbReturnType = Qnil, rbParamTypes = Qnil, rbOptions = Qnil; VALUE rbEnums = Qnil, rbConvention = Qnil, rbBlocking = Qnil; #if defined(_WIN32) || defined(__WIN32__) VALUE rbConventionStr; #endif int i, nargs; nargs = rb_scan_args(argc, argv, "21", &rbReturnType, &rbParamTypes, &rbOptions); if (nargs >= 3 && rbOptions != Qnil) { rbConvention = rb_hash_aref(rbOptions, ID2SYM(rb_intern("convention"))); rbEnums = rb_hash_aref(rbOptions, ID2SYM(rb_intern("enums"))); rbBlocking = rb_hash_aref(rbOptions, ID2SYM(rb_intern("blocking"))); } Check_Type(rbParamTypes, T_ARRAY); Data_Get_Struct(self, FunctionType, fnInfo); fnInfo->parameterCount = (int) RARRAY_LEN(rbParamTypes); fnInfo->parameterTypes = xcalloc(fnInfo->parameterCount, sizeof(*fnInfo->parameterTypes)); fnInfo->ffiParameterTypes = xcalloc(fnInfo->parameterCount, sizeof(ffi_type *)); fnInfo->nativeParameterTypes = xcalloc(fnInfo->parameterCount, sizeof(*fnInfo->nativeParameterTypes)); fnInfo->rbParameterTypes = rb_ary_new2(fnInfo->parameterCount); fnInfo->rbEnums = rbEnums; fnInfo->blocking = RTEST(rbBlocking); fnInfo->hasStruct = false; for (i = 0; i < fnInfo->parameterCount; ++i) { VALUE entry = rb_ary_entry(rbParamTypes, i); VALUE type = rbffi_Type_Lookup(entry); if (!RTEST(type)) { VALUE typeName = rb_funcall2(entry, rb_intern("inspect"), 0, NULL); rb_raise(rb_eTypeError, "Invalid parameter type (%s)", RSTRING_PTR(typeName)); } if (rb_obj_is_kind_of(type, rbffi_FunctionTypeClass)) { REALLOC_N(fnInfo->callbackParameters, VALUE, fnInfo->callbackCount + 1); fnInfo->callbackParameters[fnInfo->callbackCount++] = type; } if (rb_obj_is_kind_of(type, rbffi_StructByValueClass)) { fnInfo->hasStruct = true; } rb_ary_push(fnInfo->rbParameterTypes, type); Data_Get_Struct(type, Type, fnInfo->parameterTypes[i]); fnInfo->ffiParameterTypes[i] = fnInfo->parameterTypes[i]->ffiType; fnInfo->nativeParameterTypes[i] = fnInfo->parameterTypes[i]->nativeType; } fnInfo->rbReturnType = rbffi_Type_Lookup(rbReturnType); if (!RTEST(fnInfo->rbReturnType)) { VALUE typeName = rb_funcall2(rbReturnType, rb_intern("inspect"), 0, NULL); rb_raise(rb_eTypeError, "Invalid return type (%s)", RSTRING_PTR(typeName)); } if (rb_obj_is_kind_of(fnInfo->rbReturnType, rbffi_StructByValueClass)) { fnInfo->hasStruct = true; } Data_Get_Struct(fnInfo->rbReturnType, Type, fnInfo->returnType); fnInfo->ffiReturnType = fnInfo->returnType->ffiType; #if defined(_WIN32) || defined(__WIN32__) rbConventionStr = (rbConvention != Qnil) ? rb_funcall2(rbConvention, rb_intern("to_s"), 0, NULL) : Qnil; fnInfo->abi = (rbConventionStr != Qnil && strcmp(StringValueCStr(rbConventionStr), "stdcall") == 0) ? FFI_STDCALL : FFI_DEFAULT_ABI; #else fnInfo->abi = FFI_DEFAULT_ABI; #endif status = ffi_prep_cif(&fnInfo->ffi_cif, fnInfo->abi, fnInfo->parameterCount, fnInfo->ffiReturnType, fnInfo->ffiParameterTypes); switch (status) { case FFI_BAD_ABI: rb_raise(rb_eArgError, "Invalid ABI specified"); case FFI_BAD_TYPEDEF: rb_raise(rb_eArgError, "Invalid argument type specified"); case FFI_OK: break; default: rb_raise(rb_eArgError, "Unknown FFI error"); } fnInfo->invoke = rbffi_GetInvoker(fnInfo); return self; }