// Check that the given path exists and add it to our package search paths static bool add_path(const char* path) { #ifdef PLATFORM_IS_WINDOWS // The Windows implementation of stat() cannot cope with trailing a \ on a // directory name, so we remove it here if present. It is not safe to modify // the given path since it may come direct from getenv(), so we copy. char buf[FILENAME_MAX]; strcpy(buf, path); size_t len = strlen(path); if(path[len - 1] == '\\') { buf[len - 1] = '\0'; path = buf; } #endif struct stat s; int err = stat(path, &s); if((err != -1) && S_ISDIR(s.st_mode)) { path = stringtab(path); if(strlist_find(search, path) == NULL) search = strlist_append(search, path); } return true; }
static bool add_safe(const char* path) { path = stringtab(path); if(strlist_find(safe, path) == NULL) safe = strlist_append(safe, path); return true; }
static bool add_safe(const char* path, pass_opt_t* opt) { path = stringtab(path); strlist_t* safe = opt->safe_packages; if(strlist_find(safe, path) == NULL) opt->safe_packages = strlist_append(safe, path); return true; }
static void test_strlist(void *p) { struct StrList *sl = NULL; const char *s; sl = strlist_new(USUAL_ALLOC); str_check(lshow(sl), ""); strlist_append(sl, "1"); str_check(lshow(sl), "1"); strlist_append(sl, "2"); str_check(lshow(sl), "1,2"); strlist_append(sl, "3"); str_check(lshow(sl), "1,2,3"); s = strlist_pop(sl); str_check(s, "1"); free(s); strlist_append(sl, NULL); str_check(lshow(sl), "2,3,NULL"); strlist_free(sl); end:; }
void split(strlist_t **tokens, char *buf, char *sep, char *(*tokenizer)(char *, const char*, char **)) { char *strptr = NULL; char *tokctx; char *dupbuf = NULL; char *tok; dupbuf = strdup(buf); strptr = dupbuf; *tokens = strlist_new(); //printf("Split: '%s' on '%s'\n", buf, sep); while ((tok = tokenizer(strptr, sep, &tokctx)) != NULL) { strptr = NULL; strlist_append(*tokens, tok); } free(dupbuf); }
/// Process a "path:" scheme use command. bool use_path(ast_t* use, const char* locator, ast_t* name, pass_opt_t* options) { (void)name; const char* libpath = quoted_locator(options, use, locator); if(libpath == NULL) return false; ast_t* p = ast_nearest(use, TK_PROGRAM); program_t* prog = (program_t*)ast_data(p); pony_assert(prog->lib_args == NULL); // Not yet built args if(strlist_find(prog->libpaths, libpath) != NULL) // Ignore duplicate return true; prog->libpaths = strlist_append(prog->libpaths, libpath); return true; }
char *extract(char *format, char *buf) { char *sep = NULL; char *buffer = strdup(buf); int nbuffer = 0; int buffer_size = 1024; char *(*tokenizer)(char *, const char*, char **); /* strdup() because string literals aren't writable */ sep = strdup(" "); /* If first char is not a number or '{', use it to split instead of the * default of space */ if (!isdigit(format[0]) && (format[0] != '{') && (format[0] != '-')) { sep[0] = format[0]; format++; } //printf("extract: %s\n", format); while (format[0] != '\0') { strlist_t *tokens; strlist_t *fields; strlist_t *results; char *fieldstr; tokenizer = tokenizer_greedy; results = strlist_new(); /* All of these cases will advance the format string position */ /* This if case is a reallly lame hack */ //printf("%s\n", format); if (isdigit(format[0]) || (format[0] == '-' && isdigit(format[1]))) { asprintf(&fieldstr, "%ld", strtol(format, &format, 10)); } else if (format[0] == '{') { int fieldlen; format++; /* Skip '{' */ if (format[0] == '?') { //printf("Nongreedy\n"); format++; tokenizer = tokenizer_nongreedy; } fieldlen = strcspn(format, "}") + 1; if (format[fieldlen - 1] != '}') { fprintf(stderr, "Could not find closing '}'. Bad format: %s\n", (format - 1)); exit(1); } fieldstr = malloc(fieldlen * sizeof(char)); memset(fieldstr, 0, fieldlen * sizeof(char)); strncpy(fieldstr, format, fieldlen - 1); format += fieldlen; } else { /* Error, this format is invalid? */ fprintf(stderr, "Invalid format... %s\n", format); exit(1); } /* Split the input by sep using tokenizer */ split(&tokens, buffer, sep, tokenizer); /* fieldstr is the field selector(s). ie; "1,3" in a{1,3} */ split(&fields, fieldstr, ",", tokenizer_greedy); free(fieldstr); int i = 0; //printf("\n"); //printf("nfields selected: %d", fields->nitems); for (i = 0; i < fields->nitems; i++) { long start, end; strlist_t *range; char *field = fields->items[i]; split(&range, field, ":", tokenizer_greedy); if (range->nitems == 1) { /* Support {N} and {N:} */ start = end = strtol(range->items[0], NULL, 10); /* Support {:N} */ if (field[strlen(field) - 1] == ':') end = (start > 0) ? tokens->nitems : 0; /* Support {N:} */ if (field[0] == ':') start = 1; } else if (*field == ':') { /* Support {:} as whole all fields */ start = 0; end = 0; } else { start = strtol(range->items[0], NULL, 10); end = strtol(range->items[1], NULL, 10); } int j; /* Add 1 here because field indexing starts at 1, not 0 */ if (start < 0) { start += tokens->nitems + 1; /* For sanity, negative indexing shouldn't result in <= 0 values. */ /* XXX: Throw an error for a bad index? */ if (start < 0) start = 1; } if (end < 0) { end += tokens->nitems + 1; if (end < 0) end = start; } //printf("s/e= %ld %ld\n", start, end); /* If end is 0, and set end to start. End of 0 doesn't make sense */ if (end == 0) end = start; //printf("%ld %ld\n", start, end); if (start > end) { fprintf(stderr, "start > end is invalid: %ld > %ld\n", start, end); exit(1); } if (((start == 0) && (end != 0)) || ((start != 0) && (end == 0))) { fprintf(stderr, "Start or end cannot be 0 when the other is not 0: %ld " "and %ld\n", start, end); exit(1); } /* We start indexing at 1. */ if (start == 0) { strlist_append(results, buffer); } else { start--; end--; for (j = start; j < tokens->nitems && j <= end; j++) { strlist_append(results, tokens->items[j]); } } strlist_free(range); } /* Free buffer then allocate a new one for the new string slice */ free(buffer); buffer_size = 1024; nbuffer = 0; buffer = malloc(buffer_size); memset(buffer, 0, buffer_size); for (i = 0; i < results->nitems; i++) { char *item = results->items[i]; int len = strlen(item); if (len + nbuffer > buffer_size) { buffer_size = buffer_size * 2 + len + 1; buffer = realloc(buffer, buffer_size); } strncpy(buffer + nbuffer, item, len); nbuffer += len; if (i < results->nitems - 1) { buffer[nbuffer] = *sep; nbuffer++; } } if (format[0] != '\0') { sep[0] = format[0]; format++; } strlist_free(fields); strlist_free(tokens); strlist_free(results); } free(sep); return buffer; }
static int parsing(parse_engine* engine, json_object *pos_parse) { wchar_t c = next_token(engine); switch (c) { case 0: engine->message = (wchar_t *)L"Unexpected end"; return 1; case '[': { pos_parse->type = ARRAY; pos_parse->value.item = 0; if (next_token(engine) == ']') return 0; --engine->pos; while (1) { json_object *item = insert_item(pos_parse, 0); if (next_token(engine) == ',') { --engine->pos; } else { --engine->pos; if (parsing(engine, item)) return 1; } switch (next_token(engine)) { case ',': if (next_token(engine) == ']') return 0; --engine->pos; break; case ']': return 0; default: engine->message = (wchar_t *)L":Expected a ',' or ']'"; return 1; } } } case '{': { pos_parse->type = TABLE; pos_parse->value.item = 0; if (next_token(engine) == '}') return 0; --engine->pos; while (1) { json_object key; if (parsing(engine, &key) || key.type != TEXT) { json_object_free(&key); engine->message = (wchar_t *)L"Illegal key of pair"; return 1; } if (next_token(engine) != ':') { engine->message = (wchar_t *)L"Expected a ':'"; return 1; } json_object* item=insert_item(pos_parse, key.value.text); json_object_free(&key); if (parsing(engine, item)) { return 1; } switch (next_token(engine)) { case ';': case ',': if (next_token(engine) == '}') return 0; --engine->pos; break; case '}': return 0; default: engine->message = (wchar_t *)L"Expected a ',' or '}'"; return 1; } } } case '\'': case '"': { pos_parse->type = TEXT; pos_parse->value.text = 0; strlist str = { 0 }; while (1) { wchar_t ch = *engine->pos++; switch (ch) { case '\n': case '\r': strlist_free(&str); engine->message = (wchar_t *)L"Unterminated string"; return 1; case '\\': ch = *engine->pos++; switch (ch) { case 'b': strlist_append(&str, L"\b", 1); break; case 't': strlist_append(&str, L"\t", 1); break; case 'n': strlist_append(&str, L"\n", 1); break; case 'f': strlist_append(&str, L"\f", 1); break; case 'r': strlist_append(&str, L"\r", 1); break; case '"': case '\'': case '\\': case '/': strlist_append(&str, &ch, 1); break; case 'u': { wchar_t num = 0; for (int i = 0; i < 4; ++i) { wchar_t tmp = *engine->pos++; if (tmp >= '0'&&tmp <= '9') tmp = tmp - '0'; else if (tmp >= 'A'&&tmp <= 'F') tmp = tmp - ('A' - 10); else if (tmp >= 'a'&&tmp <= 'f') tmp = tmp - ('a' - 10); num = num << 4 | tmp; } strlist_append(&str, &num, 1); break; } default: strlist_free(&str); engine->message = (wchar_t *)L"Illegal escape"; return 1; } break; default: if (ch == c) { pos_parse->value.text = strlist_to_string(&str); strlist_free(&str); return 0; } strlist_append(&str, &ch, 1); break; } } break; } } int length = 0; char buffer[32] = { 0 }; while (c >= ' ') { if(strchr(",:]}/\\\"[{;=#", c)) break; if(length<sizeof(buffer)&&strchr("0123456789+-.AEFLNRSTUaeflnrstu",c)) { buffer[length++]=(char)c; c = *engine->pos++; } else{ engine->message=(wchar_t *)L"Illegal Value"; return 1; } } --engine->pos; if (!length) { pos_parse->type = TEXT; pos_parse->value.text = (wchar_t *)malloc(sizeof(wchar_t)); pos_parse->value.text[0] = 0; return 0; } else { if (!strcmp(buffer, "TRUE") || !strcmp(buffer, "true")) { pos_parse->type = BOOLEAN; pos_parse->value.boolean = true; return 0; } else if (!strcmp(buffer, "FALSE") || !strcmp(buffer, "false")) { pos_parse->type = BOOLEAN; pos_parse->value.boolean = false; return 0; } else if (!strcmp(buffer, "NULL") || !strcmp(buffer, "null")) { pos_parse->type = NONE; return 0; } pos_parse->type = (strstr(buffer, ".") || strstr(buffer, "e") || strstr(buffer, "E")) ? DECIMAL : INTEGER; const char *format = pos_parse->type == INTEGER ? "%lld" : "%lf"; if (sscanf(buffer, format, &pos_parse->value)) return 0; engine->message = (wchar_t *)L"Unexpected end"; return 1; } }
static void object_to_string(json_object *data, strlist *head) { switch (data->type) { case NONE: { strlist_append(head, L"null", 4); break; } case INTEGER: case DECIMAL: { char tmp[32] = { 0 }; wchar_t buffer[32] = { 0 }; const char *format = data->type == INTEGER ? "%lld" : "%lf"; sprintf(tmp, format, data->value); size_t len = strlen(tmp); for (size_t i = 0; i < len; ++i) buffer[i] = tmp[i]; strlist_append(head, buffer, len); break; } case BOOLEAN: { int len = data->value.boolean ? 4 : 5; const wchar_t *value = data->value.boolean ? L"true" : L"false"; strlist_append(head, value, len); break; } case TEXT: { strlist_append(head, L"\"", 1); strlist_append(head, data->value.text, wcslen(data->value.text)); strlist_append(head, L"\"", 1); break; } case TABLE: { json_object *item = data->value.item; int index = 0; while (item) { if(index) strlist_append(head, L",\"", 2); else strlist_append(head, L"{\"", 2); strlist_append(head, item->key, wcslen(item->key)); strlist_append(head, L"\":", 2); object_to_string(item,head); item = item->next; ++index; } strlist_append(head, L"}", 1); break; } case ARRAY: { json_object *item = data->value.item; int index = 0; while (item) { strlist_append(head, index ? L"," : L"[", 1); object_to_string(item, head); item = item->next; ++index; } strlist_append(head, L"]", 1); break; } } }
static bool sl_add(void *arg, const char *s) { return strlist_append(arg, s); }