Split a line into arguments, where every argument can be in the * following programming-language REPL-alike form: * * foo bar "newline are supported\n" and "\xff\x00otherstuff" * * The number of arguments is stored into *argc, and an array * of sds is returned. * * The caller should free the resulting array of sds strings with * sdsfreesplitres(). * * Note that sdscatrepr() is able to c
| 957 | * as in: "foo"bar or "foo' |
| 958 | */ |
| 959 | sds *sdssplitargs(const char *line, int *argc) { |
| 960 | const char *p = line; |
| 961 | char *current = NULL; |
| 962 | char **vector = NULL; |
| 963 | |
| 964 | *argc = 0; |
| 965 | while(1) { |
| 966 | /* skip blanks */ |
| 967 | while(*p && isspace(*p)) p++; |
| 968 | if (*p) { |
| 969 | /* get a token */ |
| 970 | int inq=0; /* set to 1 if we are in "quotes" */ |
| 971 | int insq=0; /* set to 1 if we are in 'single quotes' */ |
| 972 | int done=0; |
| 973 | |
| 974 | if (current == NULL) current = sdsempty(); |
| 975 | while(!done) { |
| 976 | if (inq) { |
| 977 | if (*p == '\\' && *(p+1) == 'x' && |
| 978 | is_hex_digit(*(p+2)) && |
| 979 | is_hex_digit(*(p+3))) |
| 980 | { |
| 981 | unsigned char byte; |
| 982 | |
| 983 | byte = (hex_digit_to_int(*(p+2))*16)+ |
| 984 | hex_digit_to_int(*(p+3)); |
| 985 | current = sdscatlen(current,(char*)&byte,1); |
| 986 | p += 3; |
| 987 | } else if (*p == '\\' && *(p+1)) { |
| 988 | char c; |
| 989 | |
| 990 | p++; |
| 991 | switch(*p) { |
| 992 | case 'n': c = '\n'; break; |
| 993 | case 'r': c = '\r'; break; |
| 994 | case 't': c = '\t'; break; |
| 995 | case 'b': c = '\b'; break; |
| 996 | case 'a': c = '\a'; break; |
| 997 | default: c = *p; break; |
| 998 | } |
| 999 | current = sdscatlen(current,&c,1); |
| 1000 | } else if (*p == '"') { |
| 1001 | /* closing quote must be followed by a space or |
| 1002 | * nothing at all. */ |
| 1003 | if (*(p+1) && !isspace(*(p+1))) goto err; |
| 1004 | done=1; |
| 1005 | } else if (!*p) { |
| 1006 | /* unterminated quotes */ |
| 1007 | goto err; |
| 1008 | } else { |
| 1009 | current = sdscatlen(current,p,1); |
| 1010 | } |
| 1011 | } else if (insq) { |
| 1012 | if (*p == '\\' && *(p+1) == '\'') { |
| 1013 | p++; |
| 1014 | current = sdscatlen(current,"'",1); |
| 1015 | } else if (*p == '\'') { |
| 1016 | /* closing quote must be followed by a space or |
no test coverage detected