diff --git a/components/console/linenoise/linenoise.c b/components/console/linenoise/linenoise.c index 05d57c9..babc994 100644 --- a/components/console/linenoise/linenoise.c +++ b/components/console/linenoise/linenoise.c @@ -760,31 +760,33 @@ int linenoiseEditStart(struct linenoiseState *l, char *buf, size_t buflen, const return 0; } +char *linenoiseEditMore = "If you see this, you are misusing the API: when linenoiseEditFeed() is called, if it returns linenoiseEditMore the user is yet editing the line. See the README file for more information."; + /* This function is part of the multiplexed API of linenoise, see the top * comment on linenoiseEditStart() for more information. Call this function * each time there is some data to read from the standard input file * descriptor. In the case of blocking operations, this function can just be * called in a loop, and block. * - * The function returns NULL to signal that line editing is still in progress, - * that is, the user didn't yet pressed enter / CTRL-D. Otherwise the function - * returns the pointer to the buffer and populates '*len' with the current - * buffer length. If '*len' is set to -1, some special condition occurred, and - * the caller may want to check 'errno': + * The function returns linenoiseEditMore to signal that line editing is still + * in progress, that is, the user didn't yet pressed enter / CTRL-D. Otherwise + * the function returns the pointer to the heap-allocated buffer with the + * edited line, that the user should free with linenoiseFree(). + * + * On special conditions, NULL is returned and errno is populated: * * EAGAIN if the user pressed Ctrl-C * ENOENT if the user pressed Ctrl-D + * + * Some other errno: I/O error. */ -char *linenoiseEditFeed(struct linenoiseState *l, int *len) { +char *linenoiseEditFeed(struct linenoiseState *l) { char c; int nread; char seq[3]; nread = fread(&c, 1, 1, stdin); - if (nread <= 0) { - if (len) *len = l->len; - return l->buf; - } + if (nread <= 0) return NULL; /* Only autocomplete when the callback is set. It returns < 0 when * there was an error reading from fd. Otherwise it will return the @@ -792,12 +794,9 @@ char *linenoiseEditFeed(struct linenoiseState *l, int *len) { if (c == 9 && completionCallback != NULL) { c = completeLine(l); /* Return on errors */ - if (c < 0) { - if (len) *len = -1; - return l->buf; - } + if (c < 0) return NULL; /* Read next character when 0 */ - if (c == 0) return NULL; + if (c == 0) return linenoiseEditMore; } switch(c) { @@ -813,12 +812,10 @@ char *linenoiseEditFeed(struct linenoiseState *l, int *len) { refreshLine(l); hintsCallback = hc; } - if (len) *len = l->len; - return l->buf; + return strdup(l->buf); case CTRL_C: /* ctrl-c */ errno = EAGAIN; - if (len) *len = -1; - return l->buf; + return NULL; case BACKSPACE: /* backspace */ case 8: /* ctrl-h */ linenoiseEditBackspace(l); @@ -830,9 +827,8 @@ char *linenoiseEditFeed(struct linenoiseState *l, int *len) { } else { history_len--; free(history[history_len]); - if (len) *len = -1; errno = ENOENT; - return l->buf; + return NULL; } break; case CTRL_T: /* ctrl-t, swaps current character with previous. */ @@ -912,10 +908,7 @@ char *linenoiseEditFeed(struct linenoiseState *l, int *len) { } break; default: - if (linenoiseEditInsert(l,c)) { - if (len) *len = -1; - return l->buf; - } + if (linenoiseEditInsert(l,c)) return NULL; break; case CTRL_U: /* Ctrl+u, delete the whole line. */ l->buf[0] = '\0'; @@ -941,7 +934,7 @@ char *linenoiseEditFeed(struct linenoiseState *l, int *len) { linenoiseEditDeletePrevWord(l); break; } - return NULL; + return linenoiseEditMore; } @@ -957,33 +950,28 @@ void linenoiseEditStop(struct linenoiseState *l) { * In many applications that are not event-drivern, we can just call * the blocking linenoise API, wait for the user to complete the editing * and return the buffer. */ -static int linenoiseBlockingEdit(struct linenoiseState *l, int stdin_fd, int stdout_fd, char *buf, size_t buflen, const char *prompt) +static char *linenoiseBlockingEdit(char *buf, size_t buflen, const char *prompt) { + struct linenoiseState l; /* Editing without a buffer is invalid. */ if (buflen == 0) { errno = EINVAL; - return -1; + return NULL; } - - linenoiseEditStart(l,buf,buflen,prompt); - int len; - while(1) { - char *res = linenoiseEditFeed(l,&len); - if (res != NULL) break; - } - linenoiseEditStop(l); - return len; + + linenoiseEditStart(&l,buf,buflen,prompt); + char *res; + while((res = linenoiseEditFeed(&l)) == linenoiseEditMore); + linenoiseEditStop(&l); + return res; } /* The high level function that is the main API of the linenoise library. */ char *linenoise(const char *prompt) { char buf[LINENOISE_MAX_LINE]; - int count; - struct linenoiseState l; - count = linenoiseBlockingEdit(&l,-1,-1,buf,LINENOISE_MAX_LINE,prompt); - if (count == -1) return NULL; - return strdup(buf); + char *retval = linenoiseBlockingEdit(buf,LINENOISE_MAX_LINE,prompt); + return retval; } /* This is just a wrapper the user may want to call in order to make sure @@ -991,6 +979,7 @@ char *linenoise(const char *prompt) { * created with. Useful when the main program is using an alternative * allocator. */ void linenoiseFree(void *ptr) { + if (ptr == linenoiseEditMore) return; // Protect from API misuse. free(ptr); } diff --git a/components/console/linenoise/linenoise.h b/components/console/linenoise/linenoise.h index 150e482..cfc0a33 100644 --- a/components/console/linenoise/linenoise.h +++ b/components/console/linenoise/linenoise.h @@ -46,6 +46,8 @@ extern "C" { #include /* For size_t. */ +extern char *linenoiseEditMore; + /* The linenoiseState structure represents the state during line editing. * We pass this state to functions implementing specific editing * functionalities. */ @@ -71,7 +73,7 @@ typedef struct linenoiseCompletions { /* Non blocking API. */ int linenoiseEditStart(struct linenoiseState *l, char *buf, size_t buflen, const char *prompt); -char *linenoiseEditFeed(struct linenoiseState *l, int *len); +char *linenoiseEditFeed(struct linenoiseState *l); void linenoiseEditStop(struct linenoiseState *l); void linenoiseHide(struct linenoiseState *l); void linenoiseShow(struct linenoiseState *l);