I was reading BeeJ's C programming guide and copied his readline() function, that reads a line from stdin. Due to the way it's implemented it has no problem reading multibyte characters, as it reallocates the spaces in accordance with the total amount of received bytes, and as such, it has no problem with unicode input. Here's a program with the function included:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define printPrompt printf("db > ")
/* The readLine function, allocates memory for a short string and
** reads characters into it. When the string's size limit is met,
** the same memory block is reallocated, but twice the size.
** Shamelessly stolen from BeeJ's guide to C programming |=
*/
char* read_line(void) {
int i = 0; /* Position of the current character */
int linbuf = 4; /* Size of our line in memory, will be
duplicated once the line length surpasses it */
char* lin; /* The pointer value to our line */
int c; /* The value we'll use to accept characters */
if( !(lin = malloc( linbuf*sizeof(char))) )
return NULL;
while( c = getchar(), c != '\n' && c != EOF ) {
/* Check if the amount of bytes accepted has surpassed the
* amount of memory we've allocated so far */
if(i == linbuf - 1) {
/* If it did, reallocate double the space */
linbuf *= 2;
char* tmpbuf = realloc(lin, linbuf);
/* If the space couldn't have been allocated then we'd
* run out of memory. Delete everything and abort. */
if(tmpbuf == NULL) {
free(tmpbuf);
return NULL;
}
/* If we've arrived here that means there were no
* problems, so we'll assign the newly reallocated
* memory to "lin" */
lin = tmpbuf;
}
/* Add the new character to our allocated space */
lin[i++] = c;
}
/* If we've received an EOF signal after having read 0
* characters, we'd like to delete our allocated memory and
* return a NULL */
if(c == EOF && i == 0) {
free(lin);
return NULL;
}
/* Here we'll shrink the allocated memory to perfectly fit our
* string */
if(i < linbuf - 1) {
char* tmpbuf = realloc(lin, i + 1);
if(tmpbuf != NULL)
lin = tmpbuf;
}
/* Here we'll terminate the string */
lin[i] = '\0';
/* Finally, we'll return it */
return lin;
}
int main(int argc, char* argv[]) {
char* hey = read_line();
printf("%s\n", hey);
return 0;
}
An input of
Hello, World! (:
would result in the output of
Hello, World! (:
An input of multibyte characters such as
שלום, עולם! (:
would result in the correct output of
שלום, עולם! (:
However, if I were to press the backspace key, it would only delete a one byte character, resulting in garbled output; an input of (backspaces marked as \b):
שיהיה לכם בוקר טוב\b\b\b\b\b\b\b\bערב טוב
which is supposed to end up being:
שיהיה לכם ערב טוב
actually ends up being:
�שיהיה לכם בוק�ערב טוב
My computer runs a Musl-libc version of Void Linux, and I compiled the program with both tcc and gcc, both yielding the same results.
Does this problem have to do with my libc, with my terminal (suckless st), with my kernel, or is it something I'm missing in the code? Whatever might be the case, is there any way I can handle it, preferably without using any external libraries such as ICU or what have you?