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
| 999 | * as in: "foo"bar or "foo' |
| 1000 | */ |
| 1001 | sds *sdssplitargs(const char *line, int *argc) { |
| 1002 | const char *p = line; |
| 1003 | char *current = NULL; |
| 1004 | char **vector = NULL; |
| 1005 | |
| 1006 | *argc = 0; |
| 1007 | while(1) { |
| 1008 | /* skip blanks */ |
| 1009 | while(*p && isspace(*p)) p++; |
| 1010 | if (*p) { |
| 1011 | /* get a token */ |
| 1012 | int inq=0; /* set to 1 if we are in "quotes" */ |
| 1013 | int insq=0; /* set to 1 if we are in 'single quotes' */ |
| 1014 | int done=0; |
| 1015 | |
| 1016 | if (current == NULL) current = sdsempty(); |
| 1017 | while(!done) { |
| 1018 | if (inq) { |
| 1019 | if (*p == '\\' && *(p+1) == 'x' && |
| 1020 | is_hex_digit(*(p+2)) && |
| 1021 | is_hex_digit(*(p+3))) |
| 1022 | { |
| 1023 | unsigned char byte; |
| 1024 | |
| 1025 | byte = (hex_digit_to_int(*(p+2))*16)+ |
| 1026 | hex_digit_to_int(*(p+3)); |
| 1027 | current = sdscatlen(current,(char*)&byte,1); |
| 1028 | p += 3; |
| 1029 | } else if (*p == '\\' && *(p+1)) { |
| 1030 | char c; |
| 1031 | |
| 1032 | p++; |
| 1033 | switch(*p) { |
| 1034 | case 'n': c = '\n'; break; |
| 1035 | case 'r': c = '\r'; break; |
| 1036 | case 't': c = '\t'; break; |
| 1037 | case 'b': c = '\b'; break; |
| 1038 | case 'a': c = '\a'; break; |
| 1039 | default: c = *p; break; |
| 1040 | } |
| 1041 | current = sdscatlen(current,&c,1); |
| 1042 | } else if (*p == '"') { |
| 1043 | /* closing quote must be followed by a space or |
| 1044 | * nothing at all. */ |
| 1045 | if (*(p+1) && !isspace(*(p+1))) goto err; |
| 1046 | done=1; |
| 1047 | } else if (!*p) { |
| 1048 | /* unterminated quotes */ |
| 1049 | goto err; |
| 1050 | } else { |
| 1051 | current = sdscatlen(current,p,1); |
| 1052 | } |
| 1053 | } else if (insq) { |
| 1054 | if (*p == '\\' && *(p+1) == '\'') { |
| 1055 | p++; |
| 1056 | current = sdscatlen(current,"'",1); |
| 1057 | } else if (*p == '\'') { |
| 1058 | /* closing quote must be followed by a space or |
no test coverage detected