squalylLe 10/06/2013 à 22:45
bon voila j'ai fait un readline trivial et un truc qui coupe un buffer terminé par zéro en tokens genre argc argv
je donne en vrac, pour le fun. Certainement incomplet et buggé, mais ça marchotte pour ce que ça me sert, je corrigerai plus tard ou selon vos suggestions.
ça gère correctement des trucs genre abc "de' f" (2 tokens ici)
/*released under WTFPL*/
#include <stdio.h>
#ifdef __MINGW32__
#include <conio.h>
#else
#error dont know how to disable line buffering
#endif // MINGW32
int readline(const char *prompt, char *buf, int len)
{
int n=0;
int c;
printf("%s",prompt);
while(n<(len-1)) {
c = getch();
//printf(">> %02X\n",c);
if(c=='\n' || c=='\r') { //end of line
printf("\n");
break;
} else if(c==0x08) { //backspace
if(n>0) {
n--;
printf("\x08 \x08");
}
} else if(c==0x03) { //break
buf[n++] = 0;
return E_BREAK;
} else if(c=='\t') { //tab
//manage completion later
} else {
buf[n++]=c;
printf("%c",c);
}
}
//append final zero
buf[n++] = 0;
//done
return 0;
}
/*released under WTFPL*/
#define DEBUG_PARSER
static char ** shell_parse(char *buf, int *out_total)
{
char ** toks = NULL;
char *start;
int index, count=0;
int len = strlen(buf);
int quotes = 0; //quoting state
index = 0;
start = buf;
while(buf[index]) {
#ifdef DEBUG_PARSER
printf("-> [%02X] ", buf[index]);
#endif
if(buf[index]=='\'') {
if(quotes!=2) {
if(quotes == 1) {
quotes = 0;
} else if(quotes==0) {
quotes = 1;
}
memmove(buf+index, buf+index+1, len-index);
}
#ifdef DEBUG_PARSER
printf("quote->%d\n",quotes);
#endif
} else if(buf[index]=='"') {
if(quotes!=1) {
if(quotes == 2) {
quotes = 0;
} else if(quotes==0) {
quotes = 2;
}
memmove(buf+index, buf+index+1, len-index);
}
#ifdef DEBUG_PARSER
printf("quote->%d\n",quotes);
#endif
} else if(buf[index]==' ' && quotes==0) {
//unquoted space, split token
count++;
toks = realloc(toks, count*sizeof(char*));
toks[count-1] = start; //save old token start
buf[index] = 0; //mark end of token
start = buf+index+1; //mark new token start
#ifdef DEBUG_PARSER
printf("split [%s]\n",toks[count-1]);
#endif
} else {
//normal char
#ifdef DEBUG_PARSER
printf("normal\n");
#endif
}
index++;
}
if(strlen(start)>0) {
//last characters form the last token
count++;
toks = realloc(toks, count*sizeof(char*));
toks[count-1] = start; //save old token start
buf[index] = 0; //mark end of token
#ifdef DEBUG_PARSER
printf("last-> [%s]\n", toks[count-1]);
#endif
}
*out_total = count;
return toks;
}