2015-08-05 11:30:40 +10:00
|
|
|
#include "stringop.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "string.h"
|
|
|
|
#include "list.h"
|
|
|
|
#include <strings.h>
|
|
|
|
|
|
|
|
/* Note: This returns 8 characters for trimmed_start per tab character. */
|
|
|
|
char *strip_whitespace(char *_str, int *trimmed_start) {
|
|
|
|
*trimmed_start = 0;
|
|
|
|
if (*_str == '\0')
|
|
|
|
return _str;
|
|
|
|
char *strold = _str;
|
|
|
|
while (*_str == ' ' || *_str == '\t') {
|
|
|
|
if (*_str == '\t') {
|
|
|
|
*trimmed_start += 8;
|
|
|
|
} else {
|
|
|
|
*trimmed_start += 1;
|
|
|
|
}
|
|
|
|
_str++;
|
|
|
|
}
|
|
|
|
char *str = malloc(strlen(_str) + 1);
|
|
|
|
strcpy(str, _str);
|
|
|
|
free(strold);
|
|
|
|
int i;
|
|
|
|
for (i = 0; str[i] != '\0'; ++i);
|
|
|
|
do {
|
|
|
|
i--;
|
|
|
|
} while (i >= 0 && (str[i] == ' ' || str[i] == '\t'));
|
|
|
|
str[i + 1] = '\0';
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *strip_comments(char *str) {
|
|
|
|
int in_string = 0, in_character = 0;
|
|
|
|
int i = 0;
|
|
|
|
while (str[i] != '\0') {
|
|
|
|
if (str[i] == '"' && !in_character) {
|
|
|
|
in_string = !in_string;
|
|
|
|
} else if (str[i] == '\'' && !in_string) {
|
|
|
|
in_character = !in_character;
|
|
|
|
} else if (!in_character && !in_string) {
|
2015-08-06 12:10:56 +10:00
|
|
|
if (str[i] == '#' && i == 0) {
|
2015-08-05 11:30:40 +10:00
|
|
|
str[i] = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_t *split_string(const char *str, const char *delims) {
|
|
|
|
list_t *res = create_list();
|
|
|
|
int i, j;
|
2015-08-17 06:38:54 +10:00
|
|
|
int len = strlen(str);
|
|
|
|
for (i = 0, j = 0; i < len + 1; ++i) {
|
|
|
|
if (strchr(delims, str[i]) || i == len) {
|
2015-08-05 11:30:40 +10:00
|
|
|
if (i - j == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
char *left = malloc(i - j + 1);
|
|
|
|
memcpy(left, str + j, i - j);
|
|
|
|
left[i - j] = 0;
|
|
|
|
list_add(res, left);
|
|
|
|
j = i + 1;
|
2015-08-17 06:38:54 +10:00
|
|
|
while (j <= len && str[j] && strchr(delims, str[j])) {
|
2015-08-05 11:30:40 +10:00
|
|
|
j++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void free_flat_list(list_t *list) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < list->length; ++i) {
|
|
|
|
free(list->items[i]);
|
|
|
|
}
|
|
|
|
list_free(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *code_strstr(const char *haystack, const char *needle) {
|
|
|
|
/* TODO */
|
|
|
|
return strstr(haystack, needle);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *code_strchr(const char *str, char delimiter) {
|
|
|
|
int in_string = 0, in_character = 0;
|
|
|
|
int i = 0;
|
|
|
|
while (str[i] != '\0') {
|
|
|
|
if (str[i] == '"' && !in_character) {
|
|
|
|
in_string = !in_string;
|
|
|
|
} else if (str[i] == '\'' && !in_string) {
|
|
|
|
in_character = !in_character;
|
|
|
|
} else if (!in_character && !in_string) {
|
|
|
|
if (str[i] == delimiter) {
|
|
|
|
return (char *)str + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int unescape_string(char *string) {
|
|
|
|
/* TODO: More C string escapes */
|
|
|
|
int len = strlen(string);
|
|
|
|
int i;
|
|
|
|
for (i = 0; string[i]; ++i) {
|
|
|
|
if (string[i] == '\\') {
|
|
|
|
--len;
|
2015-08-17 06:38:54 +10:00
|
|
|
int shift = 0;
|
2015-08-05 11:30:40 +10:00
|
|
|
switch (string[++i]) {
|
|
|
|
case '0':
|
|
|
|
string[i - 1] = '\0';
|
2015-08-17 06:38:54 +10:00
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
string[i - 1] = '\a';
|
2015-08-17 06:38:54 +10:00
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
string[i - 1] = '\b';
|
2015-08-17 06:38:54 +10:00
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
2015-08-17 06:38:54 +10:00
|
|
|
case 'f':
|
|
|
|
string[i - 1] = '\f';
|
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
string[i - 1] = '\n';
|
2015-08-17 06:38:54 +10:00
|
|
|
shift = 1;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
string[i - 1] = '\r';
|
|
|
|
shift = 1;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
string[i - 1] = '\t';
|
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
string[i - 1] = '\v';
|
2015-08-17 06:38:54 +10:00
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
2015-08-17 06:38:54 +10:00
|
|
|
case '\\':
|
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
2015-08-17 06:38:54 +10:00
|
|
|
case '\'':
|
|
|
|
string[i - 1] = '\'';
|
|
|
|
shift = 1;
|
|
|
|
break;
|
|
|
|
case '\"':
|
|
|
|
string[i - 1] = '\"';
|
|
|
|
shift = 1;
|
|
|
|
break;
|
|
|
|
case '?':
|
|
|
|
string[i - 1] = '?';
|
|
|
|
shift = 1;
|
2015-08-05 11:30:40 +10:00
|
|
|
break;
|
2015-08-17 06:38:54 +10:00
|
|
|
case 'x':
|
|
|
|
{
|
|
|
|
unsigned char c = 0;
|
|
|
|
shift = 1;
|
|
|
|
if (string[i+1] >= '0' && string[i+1] <= '9') {
|
|
|
|
shift = 2;
|
|
|
|
c = string[i+1] - '0';
|
|
|
|
if (string[i+2] >= '0' && string[i+2] <= '9') {
|
|
|
|
shift = 3;
|
|
|
|
c *= 0x10;
|
|
|
|
c += string[i+2] - '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
string[i - 1] = c;
|
|
|
|
}
|
2015-08-05 11:30:40 +10:00
|
|
|
}
|
2015-08-17 06:38:54 +10:00
|
|
|
memmove(string + i, string + i + shift, len - i);
|
2015-08-05 11:30:40 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
2015-08-06 12:40:38 +10:00
|
|
|
|
|
|
|
char *join_args(char **argv, int argc) {
|
|
|
|
int len = 0, i;
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
len += strlen(argv[i]) + 1;
|
|
|
|
}
|
|
|
|
char *res = malloc(len);
|
|
|
|
len = 0;
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
strcpy(res + len, argv[i]);
|
|
|
|
len += strlen(argv[i]);
|
|
|
|
res[len++] = ' ';
|
|
|
|
}
|
|
|
|
res[len - 1] = '\0';
|
|
|
|
return res;
|
|
|
|
}
|