/** * non-declaration statement */ do_statement () { if (amatch ("if", 2)) { doif (); lastst = STIF; } else if (amatch ("while", 5)) { dowhile (); lastst = STWHILE; } else if (amatch ("switch", 6)) { doswitch (); lastst = STSWITCH; } else if (amatch ("do", 2)) { dodo (); need_semicolon (); lastst = STDO; } else if (amatch ("for", 3)) { dofor (); lastst = STFOR; } else if (amatch ("return", 6)) { doreturn (); need_semicolon (); lastst = STRETURN; } else if (amatch ("break", 5)) { dobreak (); need_semicolon (); lastst = STBREAK; } else if (amatch ("continue", 8)) { docont (); need_semicolon (); lastst = STCONT; } else if (match (";")) ; else if (amatch ("case", 4)) { docase (); lastst = statement (NO); } else if (amatch ("default", 7)) { dodefault (); lastst = statement (NO); } else if (match ("__asm__")) { doasm (); lastst = STASM; } else if (match("#")) { kill(); } else if (match ("{")) do_compound (NO); else { expression (YES); /* if (match (":")) { dolabel (); lastst = statement (NO); } else { */ need_semicolon (); lastst = STEXP; /* } */ } }
void dofile(FILE *fp, int translating) { char buf[1024], sparebuf[1024], *p; /* * Command syntax is: * * - "seed <integer>" sets a random seed * * - "test <function> <ntests>" generates random test lines * * - "<function> op1=foo [op2=bar]" generates a specific test * - "func=<function> op1=foo [op2=bar]" does the same * - "func=<function> op1=foo result=bar" will just output the line as-is * * - a semicolon or a blank line is ignored */ while (fgets(buf, sizeof(buf), fp)) { buf[strcspn(buf, "\r\n")] = '\0'; strcpy(sparebuf, buf); p = buf; while (*p && isspace(*p)) p++; if (!*p || *p == ';') { /* Comment or blank line. Only print if `translating' is set. */ if (translating) printf("%s\n", buf); continue; } if (!strncmp(buf, "seed ", 5)) { seed_random(atoi(buf+5)); } else if (!strncmp(buf, "random=", 7)) { /* * Copy 'random=on' / 'random=off' lines unconditionally * to the output, so that random test failures can be * accumulated into a recent-failures-list file and * still identified as random-in-origin when re-run the * next day. */ printf("%s\n", buf); } else if (!strncmp(buf, "test ", 5)) { char *p = buf+5; char *q; int ntests, i; q = p; while (*p && !isspace(*p)) p++; if (*p) *p++ = '\0'; while (*p && isspace(*p)) p++; if (*p) ntests = atoi(p); else ntests = 100; /* *shrug* */ for (i = 0; i < nfunctions; i++) { if (!strcmp(q, functions[i].name)) { gencases(&functions[i], ntests); break; } } if (i == nfunctions) { fprintf(stderr, "unknown test `%s'\n", q); } } else { /* * Parse a specific test line. */ uint32 ops[8], result[8]; int got_op = 0; /* &1 for got_op1, &4 for got_op3 etc. */ Testable *f; char *q, *r; int i; int got_result = 0, got_errno_in = 0; for (q = strtok(p, " \t"); q; q = strtok(NULL, " \t")) { r = strchr(q, '='); if (!r) { f = find_function(q); } else { *r++ = '\0'; if (!strcmp(q, "func")) f = find_function(r); else if (!strcmp(q, "op1") || !strcmp(q, "op1r")) { get_operand(r, f, &ops[0], &ops[1]); got_op |= 1; } else if (!strcmp(q, "op2") || !strcmp(q, "op1i")) { get_operand(r, f, &ops[2], &ops[3]); got_op |= 2; } else if (!strcmp(q, "op2r")) { get_operand(r, f, &ops[4], &ops[5]); got_op |= 4; } else if (!strcmp(q, "op2i")) { get_operand(r, f, &ops[6], &ops[7]); got_op |= 8; } else if (!strcmp(q, "result") || !strcmp(q, "resultr")) { get_operand(r, f, &result[0], &result[1]); got_result |= 1; } else if (!strcmp(q, "resulti")) { get_operand(r, f, &result[4], &result[5]); got_result |= 2; } else if (!strcmp(q, "res2")) { get_operand(r, f, &result[2], &result[3]); got_result |= 4; } else if (!strcmp(q, "errno_in")) { got_errno_in = 1; } } } /* * Test cases already set up by the input are not * reprocessed by default, unlike the fplib tests. (This * is mostly for historical reasons, because we used to * use a very slow and incomplete internal reference * implementation; now our ref impl is MPFR/MPC it * probably wouldn't be such a bad idea, though we'd still * have to make sure all the special cases came out * right.) If translating==2 (corresponding to the -T * command-line option) then we regenerate everything * regardless. */ if (got_result && translating < 2) { if (f) vet_for_decline(f, ops, result, got_errno_in); puts(sparebuf); continue; } if (f && got_op==(1<<nargs_(f))-1) { /* * And do it! */ docase(f, ops); } } } }