2024-02-20 04:08:45 +05:30
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*
|
2024-03-10 14:20:09 +05:30
|
|
|
* TODO: Figure out potential problems
|
2024-03-10 16:38:28 +05:30
|
|
|
* 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)`
|
2024-02-20 04:08:45 +05:30
|
|
|
*/
|
|
|
|
|
|
|
|
#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;
|
|
|
|
|
2024-03-10 16:42:05 +05:30
|
|
|
// NOTE: if the file is STDIN, flush STDOUT before waiting for input to
|
|
|
|
// make sure a prompt is displayed
|
|
|
|
fflush(stdout);
|
|
|
|
|
2024-02-20 04:08:45 +05:30
|
|
|
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;
|
2024-03-10 16:42:51 +05:30
|
|
|
freadln_success_epilogue;
|
2024-02-20 04:08:45 +05:30
|
|
|
} 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;
|
2024-03-10 16:42:51 +05:30
|
|
|
freadln_success_epilogue;
|
2024-02-20 04:08:45 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
*output = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = 0;
|
2024-03-10 16:42:51 +05:30
|
|
|
freadln_success_epilogue;
|
2024-02-20 04:08:45 +05:30
|
|
|
}
|