cerror-handlingprintfstdoutcode-generation

Is there any way to recover from a printf()/puts() error?


Whilst interpreting and transpiling Brainfuck, I have this series of calls to printf()/puts():

while (ip < ops->count) {
        Op op = ops->items[ip];

        switch (op.kind) {
            case '+':
                printf("    t.mem[t.head] += %zu;\n", op.operand);
                ++ip;
                break;
            case '-':
                printf("    t.mem[t.head] -= %zu;\n", op.operand);
                ++ip;
                break;
            case '.':
                printf("    xputchar_many(&t, %zu);\n", op.operand);
                ++ip;
                break;
            case ',':
                printf("    xgetchar_many(&t, %zu);{\n", op.operand);
                ++ip;
                break;
            case '>':
                printf("    t.head += %zu;\n\n"
                       "    grow_tape_and_append_many_zeroes(&t);\n", op.operand);
                ++ip;
                break;
            case '<':
                printf("    t.head = t.head < %zu ? t.count - (%zu - t.head) : t.head - %zu;\n",
                       op.operand, op.operand, op.operand);
                ++ip;
                break;
            case '[':
                puts("    while (t.mem[t.head] != 0) {");
                ++ip;
                break;
            case ']':
                puts("    }");
                ++ip;
                break;
        }
    }

The calls to puts()/printf() are generating the code.

I have two questions:

Is there any chance of recovery after printf() fails (i.e. return a negative integer) or puts() fail (i.e. return EOF)? (I am of the opinion no.)

If no, is calling fprintf(stderr, ...) before exiting still useful? (I am of the opinion yes.)


Solution

  • Is there any chance of recovery after printf() fails (i.e. return a negative integer) or puts() fail (i.e. return EOF)? (I am of the opinion no.)

    There is unlikely to be anything that the program can do by itself to recover. As another answer points out, you can clear the destination FILE's error indicator and try again, but there's no particular reason to expect that that will be sufficient (but also no reason suppose that it couldn't be sufficient in any particular instance).

    However, you're probably asking the wrong question. You're writing a Brainfuck transpiler. The first two questions you should be asking here are

    I claim that no, for this utility, it is not worth spending time or effort on an error-recovery mechanism for I/O errors. Such errors are unlikely to occur and unlikely to have good recovery options anyway, and the utility's role is not critical or sensitive. A recovery strategy for such errors would very likely be a wasted effort.

    Instead, then, the program should probably just attempt to print a diagnostic to stderr and exit with a failure status, or maybe even abort().

    You wrote in comments:

    The problem is wrongly generated code, or half generated code, without an error indication.

    Either exiting with a failure status or terminating because of a signal (which would be the result of calling abort()) is detectable in the environment from which the program is launched, so either of these options provides an error indication that can alert about the generated code being faulty as a result of the kind of error you ask about.

    There may be other indications the program can provide too. For example, as @JonathanLeffler noted in comments, if the output were going to a regular file whose path the program knew, then it might attempt to remove that file when terminating because of an I/O error. Whether that or any other such behavior would be desirable is a judgement for you to make.