Cell* cell_add_str(Cell *p, const char *src) { int len; if (NULL == p) return NULL; len = strlen(src)+1; if ((len + p->length) > p->allocsize) { if (NULL == cell_realloc(p, len + p->length)) return NULL; } strncpy(&p->data[p->length], src, len); p->length = p->length + len-1; return p; }
Cell* cell_add_char(Cell *p, const char src) { int len; if (NULL == p) return NULL; len = 2; if ((len + p->length) > p->allocsize) { if (NULL == cell_realloc(p, len + p->length)) return NULL; } p->data[p->length] = src; p->data[p->length+1] = 0; p->length = p->length + len-1; return p; }
ReaderState* read_char(char c, ReaderState* rs) { Cell* cell = rs->cell; Cell* new_cell; if (!cell) { // make a root cell = alloc_nil(); cell->next = alloc_nil(); *rs->stack = cell; } if (rs->state == PST_ATOM) { if (c==' ' || c==13 || c==10) { // skip whitespace } else if (c==';') { // comment rs->state = PST_COMMENT; } else if (c>='0' && c<='9') { rs->state = PST_NUM; rs->valuestate = VST_DEFAULT; new_cell = alloc_int(0); new_cell->value = c-'0'; cell->addr = new_cell; } else if (c=='(') { // start list new_cell = alloc_nil(); cell->addr = new_cell; *rs->stack = cell; cell = new_cell; rs->stack++; rs->level++; rs->state = PST_ATOM; } else if (c==')') { // end of list cell = reader_end_list(cell, rs); } else if (c=='[') { // bytes (hex notation) rs->state = PST_BYTES; rs->sym_len = 0; new_cell = alloc_bytes(); cell->addr = new_cell; } else if (c=='"') { // string rs->state = PST_STR; rs->sym_len = 0; new_cell = alloc_string(); cell->addr = new_cell; } else { // symbol rs->state = PST_SYM; rs->sym_len = 1; new_cell = alloc_sym(0); new_cell->addr = cell_malloc(SYM_INIT_BUFFER_SIZE); memset(new_cell->addr, 0, SYM_INIT_BUFFER_SIZE); ((char*)new_cell->addr)[0] = c; new_cell->size = SYM_INIT_BUFFER_SIZE; // buffer space cell->addr = new_cell; } } else if (rs->state == PST_COMMENT) { //printf("c[%c]\n",c); if (c=='\n' || c=='0') { rs->state = PST_ATOM; } } else if (rs->state == PST_NUM || rs->state == PST_NUM_NEG) { if (c>='0' && c<='9' || ((rs->valuestate == VST_HEX && c>='a' && c<='f'))) { // build number Cell* vcell = (Cell*)cell->addr; int mul = 10; if (rs->valuestate == VST_HEX) mul = 16; int d = 0; if (c>='a') { d = 10+(c-'a'); } else { d = c-'0'; } if (rs->state == PST_NUM_NEG) { vcell->value = vcell->value*mul - d; } else { vcell->value = vcell->value*mul + d; } } else if (c==' ' || c==13 || c==10) { cell = reader_next_list_cell(cell, rs); } else if (c==')') { cell = reader_end_list(cell, rs); } else if (c=='x') { rs->valuestate = VST_HEX; } else { rs->state = PST_ERR_UNEXP_JUNK_IN_NUMBER; } } else if (rs->state == PST_SYM || rs->state == PST_STR) { int append = 0; if (rs->state == PST_STR) { if (c=='"') { // string is over Cell* vcell = (Cell*)cell->addr; vcell->size = (rs->sym_len); cell = reader_next_list_cell(cell, rs); } else { append = 1; } } else { if (c==')') { cell = reader_end_list(cell, rs); } else if (c==' ' || c==13 || c==10) { cell = reader_next_list_cell(cell, rs); } else if (rs->state == PST_SYM && (c>='0' && c<='9')) { Cell* vcell = (Cell*)cell->addr; // detect negative number if (((char*)vcell->addr)[0] == '-') { // we're actually not a symbol, correct the cell. rs->state = PST_NUM_NEG; vcell->tag = TAG_INT; vcell->value = -(c-'0'); } } else { append = 1; } } if (append) { // build symbol/string Cell* vcell = (Cell*)cell->addr; int idx = rs->sym_len; rs->sym_len++; if (rs->sym_len>=vcell->size-1) { // grow buffer vcell->addr = cell_realloc(vcell->addr, vcell->size, 2*vcell->size); memset(vcell->addr+vcell->size, 0, vcell->size); vcell->size = 2*vcell->size; } ((char*)vcell->addr)[idx] = c; } } else if (rs->state == PST_BYTES) { if (c==']') { Cell* vcell = (Cell*)cell->addr; vcell->size = (rs->sym_len)/2; cell = reader_next_list_cell(cell, rs); } else if ((c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F')) { int n = c; if (n>='a') n-=('a'-'9'-1); // hex 'a' to 10 offset if (n>='A') n-=('A'-'9'-1); // hex 'a' to 10 offset n-='0'; // char to value Cell* vcell = (Cell*)cell->addr; int idx = rs->sym_len; rs->sym_len++; if (rs->sym_len>=(vcell->size/2)-1) { // grow buffer vcell->addr = cell_realloc(vcell->addr, vcell->size, 2*vcell->size); // TODO: check the math memset(vcell->addr+vcell->size, 0, vcell->size); vcell->size = 2*vcell->size; } if (idx%2==0) { // even digit ((byte*)vcell->addr)[idx/2] = n<<4; // high nybble } else { // odd digit ((byte*)vcell->addr)[idx/2] |= n; } } else if (c==' ' || c==13 || c==10) { // skip } else { rs->state = PST_ERR_UNEXP_JUNK_IN_BYTES; } } rs->cell = cell; return rs; }