/** * @brief Reallocate the space for a given string * * @param str the string to reallocate space for * @param size the new size to assume, or if 0, the size is doubled * @return the reallocated string */ lstring_t *lstr_realloc(lstring_t *str, size_t size) { assert(str->hash == 0); if (size == 0) size = str->length * 2; str->length = size; return gc_realloc(str, sizeof(lstring_t) + size); }
atom_p read(FILE* input) { fscanf(input, " "); if (feof(input)) return NULL; char* str = NULL; if ( fscanf(input, "\"%m[^\"]\"", &str) == 1 ) { atom_p atom = gc_alloc(sizeof(atom_t)); atom->type = T_STR; atom->str = gc_alloc(strlen(str) + 1); strcpy(atom->str, str); free(str); return atom; } int c = getc(input); if ( isdigit(c) ) { double value = c - '0'; while ( (c = getc(input)), c >= '0' && c <= '9' ) { value = value * 10; value += c - '0'; } if (c == '.') { double fraction = 0.1; while ( (c = getc(input)), c >= '0' && c <= '9' ) { value += (c - '0') * fraction; fraction /= 10; } } ungetc(c, input); atom_p atom = gc_alloc(sizeof(atom_t)); atom->type = T_NUM; atom->num = value; return atom; } else if (c == '(') { atom_p atom = gc_alloc(sizeof(atom_t)); atom->type = T_ARRAY; atom->array.len = 0; atom->array.ptr = NULL; int c = 0; while (true) { fscanf(input, " "); if ( (c = getc(input)) == ')' ) return atom; ungetc(c, input); atom_p item = read(input); if (item == NULL) return error_atom("unexpected EOF while reading array elements"); atom->array.ptr = gc_realloc(atom->array.ptr, atom->array.len * sizeof(atom->array.ptr[0]), (atom->array.len + 1) * sizeof(atom->array.ptr[0])); atom->array.len += 1; atom->array.ptr[atom->array.len - 1] = item; } } else if (c == '{') { atom_p atom = gc_alloc_zeroed(sizeof(atom_t)); atom->type = T_OBJ; char c = 0; fscanf(input, " %c", &c); if (c == '}') return atom; ungetc(c, input); do { char* key = NULL; if ( fscanf(input, " %m[^:{}() \f\n\r\t\v]", &key) != 1 ) return error_atom("expected object property name after '{' or ','"); fscanf(input, " %c", &c); if (c != ':') return error_atom("expected ':' after object property name"); atom_p value = read(input); hash_set(atom, key, value); } while( fscanf(input, " %c", &c) == 1 && c == ',' ); if (c != '}') return error_atom("expected '}' or ',' after object property value"); return atom; } else { ungetc(c, input); } if ( fscanf(input, " %m[^:{}() \f\n\r\t\v]", &str) == 1 ) { atom_p atom = NULL; if ( strcmp(str, "nil") == 0 ) { atom = nil_atom; free(str); } else if ( strcmp(str, "true") == 0 ) { atom = true_atom; free(str); } else if ( strcmp(str, "false") == 0 ) { atom = false_atom; free(str); } else { atom = gc_alloc_uncollected(sizeof(atom_t)); atom->type = T_SYM; atom->sym = gc_alloc(strlen(str) + 1); strcpy(atom->sym, str); free(str); } return atom; } fscanf(input, "%*[^\n]"); return error_atom("syntax error, ignoring rest of line"); }
extern "C" void* gc_compat_realloc(void* ptr, size_t sz) { if (ptr == NULL) return gc_alloc(sz, GCKind::CONSERVATIVE); return gc_realloc(ptr, sz); }
/* * Read a string. */ static char *token_readstring(context_t cxt, char end) { size_t size = 128; size_t len = 0; char *buf = (char *)gc_malloc(size+1); char c; while (*cxt->str != end) { if (!isprint(*cxt->str)) return NULL; if (len >= size) { size *= 2; buf = (char *)gc_realloc(buf, size); } c = *cxt->str; buf[len++] = *cxt->str++; if (c == '\\') { c = *cxt->str++; switch (c) { case '\0': return NULL; case '0': buf[len-1] = '\0'; break; case 'n': buf[len-1] = '\n'; break; case 'r': buf[len-1] = '\r'; break; case 't': buf[len-1] = '\r'; break; case 'a': buf[len-1] = '\a'; break; case 'b': buf[len-1] = '\b'; break; case 'f': buf[len-1] = '\f'; break; case 'x': { char tmp[3]; tmp[0] = *cxt->str++; if (!isxdigit(tmp[0])) return NULL; tmp[1] = *cxt->str++; if (!isxdigit(tmp[1])) return NULL; tmp[2] = '\0'; unsigned x; if (sscanf(tmp, "%x", &x) != 1) return NULL; buf[len-1] = (char)x; break; } default: if (c == '\n') cxt->line++; buf[len-1] = c; break; } } } buf[len] = '\0'; buf = gc_realloc(buf, len+1); cxt->str++; return buf; }
/* * Read a line from the prompt. */ extern char *prompt(bool silent, FILE *input, history_t *state) { const char *prompt = (silent? "": "> "); while (true) { #ifndef WINDOWS if (use_readline && input == stdin) { // Set the state: if (use_state) { if (*state != NULL) { history_set_history_state((HISTORY_STATE *)*state); free(*state); *state = NULL; } else history_set_history_state(empty_state); } // Readline: char *line = readline(prompt); if (line != NULL) { bool all_space = true; for (size_t i = 0; line[i]; i++) { if (!isspace(line[i])) { all_space = false; break; } } if (!all_space) add_history(line); } if (use_state) *state = (history_t)history_get_history_state(); return line; } #endif /* WINDOWS */ // Non-readline: size_t size = 128, len = 0; char *line = gc_malloc(size*sizeof(char)); char c; fputs(prompt, stdout); while (!feof(input) && !ferror(input) && (c = getc(input)) != '\n') { if (len >= size-1) { size = (3 * size) / 2; line = (char *)gc_realloc(line, size*sizeof(char)); } line[len++] = c; } if (feof(input) || ferror(input)) return NULL; line[len] = '\0'; return line; } }