/* * freadln.c * * The `freadln` function reads a line from STDIN into a string, allocating * memory for it. * * Author: Intel A80486DX2-66 * License: Creative Commons Zero 1.0 Universal * * TODO: Figure out potential problems * TODO: Add 'flushing' of STDIN (while there are characters, read them) before * the input reading loop to avoid input queues * TODO: Add the feature of reading from arbitrary file, then extract a macro: * `#define finreadln(output, length_out) freadln(stdin, output, length_out)` */ #include "freadln.h" ssize_t freadln(char** output, size_t* length_out) { /* * The length of STDIN line is counted without any terminating characters. * * return value: * freadln_OK: no errors, the length of STDIN line has been stored in * `length_out` * freadln_ERROR: an error occurred (see errno) * >= 0: length of stdin line */ if (output == NULL) return freadln_ERROR; // NOTE: if the file is STDIN, flush STDOUT before waiting for input to // make sure a prompt is displayed fflush(stdout); freadln_length_type length = 0; *output = malloc((length + 1) * sizeof(char)); if (*output == NULL) return freadln_ERROR; int character; while ((character = fgetc(stdin)) != EOF /* stop on a newline character: */ && character != '\n') { (*output)[length] = (char) character; // integer overflow and integer limit check, to keep array boundaries if ((freadln_length_type) (length + 2) <= (freadln_length_type) length) { errno = ERANGE; freadln_success_epilogue; } else length++; char* temp = realloc(*output, (length + 1) * sizeof(char)); // If the function fails to allocate new memory, return the string that // has already been accumulated. if (temp == NULL) { // keep errno; freadln_success_epilogue; } *output = temp; } errno = 0; freadln_success_epilogue; }