static uclptr_t STRING_create (const void* sample_data) { if (sizeof(char*) <= sizeof(cell_t)) { uclptr_t storage_index = cell_alloc(); if (storage_index != NIL) { int length = strlen(sample_data) + 1; //char **storage_cell_ptr = (char**)&uclmem[storage_index]; char **storage_cell_ptr = (char**)&CONTAINER(storage_index); MANAGED(storage_index) = 1; *storage_cell_ptr = (char*)malloc(length); memset (*storage_cell_ptr, 0, length); strcpy (*storage_cell_ptr, sample_data); return storage_index; } } else /* физический указатель очень велик и не помещается даже на место целой ячейки */ { int length = strlen(sample_data) + 1; char *src = (char*)malloc(length); strcpy (src, sample_data); return chop (&src, sizeof(void*)); } return NIL; }
static void cell(struct tbl_node *tbl, struct tbl_row *rp, int ln, const char *p, int *pos) { int i; enum tbl_cellt c; /* Handle leading vertical lines */ while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') { if (p[*pos] == '|') { if (rp->vert < 2) rp->vert++; else mandoc_msg(MANDOCERR_TBLLAYOUT_VERT, tbl->parse, ln, *pos, NULL); } (*pos)++; } again: while (p[*pos] == ' ' || p[*pos] == '\t') (*pos)++; if (p[*pos] == '.' || p[*pos] == '\0') return; /* Parse the column position (`c', `l', `r', ...). */ for (i = 0; i < KEYS_MAX; i++) if (tolower((unsigned char)p[*pos]) == keys[i].name) break; if (i == KEYS_MAX) { mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse, ln, *pos, "%c", p[*pos]); (*pos)++; goto again; } c = keys[i].key; /* Special cases of spanners. */ if (c == TBL_CELL_SPAN) { if (rp->last == NULL) mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN, tbl->parse, ln, *pos, NULL); else if (rp->last->pos == TBL_CELL_HORIZ || rp->last->pos == TBL_CELL_DHORIZ) c = rp->last->pos; } else if (c == TBL_CELL_DOWN && rp == tbl->first_row) mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN, tbl->parse, ln, *pos, NULL); (*pos)++; /* Allocate cell then parse its modifiers. */ mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos); }
/** Evaluate a function call */ value_t eval_call( clos_t* callee, array_t* arg_exprs, clos_t* caller, value_t* caller_locals ) { ast_fun_t* fptr = callee->fun; assert (fptr != NULL); if (arg_exprs->len != fptr->param_decls->len) { printf("argument count mismatch\n"); exit(-1); } // Allocate space for the local variables value_t* callee_locals = alloca( sizeof(value_t) * fptr->local_decls->len ); // Allocate mutable cells for the escaping variables for (size_t i = 0; i < fptr->esc_locals->len; ++i) { ast_decl_t* decl = array_get(fptr->esc_locals, i).word.decl; assert (decl->esc); assert (decl->idx < fptr->local_decls->len); callee_locals[decl->idx] = value_from_obj((heapptr_t)cell_alloc()); } // Evaluate the argument values for (size_t i = 0; i < arg_exprs->len; ++i) { //printf("evaluating arg %ld\n", i); heapptr_t param_decl = array_get_ptr(fptr->param_decls, i); // Evaluate the parameter value value_t arg_val = eval_expr( array_get_ptr(arg_exprs, i), caller, caller_locals ); // Assign the value to the parameter eval_assign( param_decl, arg_val, callee, callee_locals ); } // Evaluate the unit function body in the local frame return eval_expr(fptr->body_expr, callee, callee_locals); }
static int cell(struct tbl_node *tbl, struct tbl_row *rp, int ln, const char *p, int *pos) { int i; enum tbl_cellt c; /* Parse the column position (`r', `R', `|', ...). */ for (i = 0; i < KEYS_MAX; i++) if (tolower((unsigned char)p[*pos]) == keys[i].name) break; if (KEYS_MAX == i) { TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos); return(0); } c = keys[i].key; /* * If a span cell is found first, raise a warning and abort the * parse. FIXME: recover from this somehow? */ if (NULL == rp->first && TBL_CELL_SPAN == c) { TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos); return(0); } (*pos)++; /* Extra check for the double-vertical. */ if (TBL_CELL_VERT == c && '|' == p[*pos]) { (*pos)++; c = TBL_CELL_DVERT; } /* Disallow adjacent spacers. */ if (rp->last && (TBL_CELL_VERT == c || TBL_CELL_DVERT == c) && (TBL_CELL_VERT == rp->last->pos || TBL_CELL_DVERT == rp->last->pos)) { TBL_MSG(tbl, MANDOCERR_TBLLAYOUT, ln, *pos - 1); return(0); } /* Allocate cell then parse its modifiers. */ return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos)); }
static uclptr_t INTEGER32_create (const void* sample_data) /* Теперь надо посмотреть, влезает ли 32-битное число в поле CDR. * Если не влезает, оно будет храниться в отдельной ячейке (сделаем смелое предположение о том, что туда-то уж оно влезет). */ { if (sizeof(int32_t) != sizeof(uclptr_t)) /* определяется на этапе компиляции */ { uclptr_t storage_index = cell_alloc(); /* возьмём ещё одну ячейку */ //int32_t **storage_cell_ptr = (int32_t**)&uclmem[storage_index]; /* представим, что это указатель на int */ int32_t **storage_cell_ptr = (int32_t**)&CONTAINER(storage_index); /* представим, что это указатель на int */ MANAGED(storage_index) = 1; *storage_cell_ptr = (int32_t*)sample_data; /* положим его туда */ return storage_index; /* вернём индекс ячейки хранения */ } else return (uint32_t)((intptr_t)sample_data); }
static uclptr_t VECTOR_create (const void* sample_data) /* параметр - uint32_t, количество выделяемых ячеек. */ /* Эта функция только создаёт пустой вектор, его наполнение - забота совершенно другой конструкции. * */ { uint32_t i, n = (uintptr_t)sample_data; uint32_t size = (n * sizeof(uclptr_t)); /* смело! А вдруг упрёмся в ограничение? */ ucl_vector_t *vector; uclptr_t storage_index; if (sizeof(void*) <= sizeof(cell_t)) /* если указатель на кучу влезает целиком в поле container, то используем эту схему хранения */ { storage_index = cell_alloc(); if (storage_index != NIL) { ucl_vector_t **storage_cell_ptr = (ucl_vector_t**)&CONTAINER(storage_index); //GC(storage_index) = GC_TRANSIENT; MANAGED(storage_index) = 1; *storage_cell_ptr = (ucl_vector_t*)malloc(sizeof(ucl_vector_t)); /* выделяем память под дескриптор ветора */ vector = *storage_cell_ptr; } else { printf ("Panic stop: no free memory left!\n"); exit(-1); } } else /* если физический указатель очень велик и не помещается даже на место целой ячейки, тогда используем другую схему хранения - чоппер! */ { vector = (ucl_vector_t*)malloc(sizeof(ucl_vector_t)); storage_index = chop (&vector, sizeof(ucl_vector_t*)); } vector->length = n; vector->ptr = (uclptr_t*)malloc(size); for (i=0; i < vector->length; i++) { vector->ptr[i] = NIL; } return storage_index; }
void tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos) { struct tbl_row *rp; rp = NULL; for (;;) { /* Skip whitespace before and after each cell. */ while (p[pos] == ' ' || p[pos] == '\t') pos++; switch (p[pos]) { case ',': /* Next row on this input line. */ pos++; rp = NULL; continue; case '\0': /* Next row on next input line. */ return; case '.': /* End of layout. */ pos++; tbl->part = TBL_PART_DATA; /* * When the layout is completely empty, * default to one left-justified column. */ if (tbl->first_row == NULL) { tbl->first_row = tbl->last_row = mandoc_calloc(1, sizeof(*rp)); } if (tbl->first_row->first == NULL) { mandoc_msg(MANDOCERR_TBLLAYOUT_NONE, tbl->parse, ln, pos, NULL); cell_alloc(tbl, tbl->first_row, TBL_CELL_LEFT); return; } /* * Search for the widest line * along the left and right margins. */ for (rp = tbl->first_row; rp; rp = rp->next) { if (tbl->opts.lvert < rp->vert) tbl->opts.lvert = rp->vert; if (rp->last != NULL && rp->last->col + 1 == tbl->opts.cols && tbl->opts.rvert < rp->last->vert) tbl->opts.rvert = rp->last->vert; /* If the last line is empty, drop it. */ if (rp->next != NULL && rp->next->first == NULL) { free(rp->next); rp->next = NULL; tbl->last_row = rp; } } return; default: /* Cell. */ break; } /* * If the last line had at least one cell, * start a new one; otherwise, continue it. */ if (rp == NULL) { if (tbl->last_row == NULL || tbl->last_row->first != NULL) { rp = mandoc_calloc(1, sizeof(*rp)); if (tbl->last_row) tbl->last_row->next = rp; else tbl->first_row = rp; tbl->last_row = rp; } else rp = tbl->last_row; } cell(tbl, rp, ln, p, &pos); } }
static int cell(struct tbl_node *tbl, struct tbl_row *rp, int ln, const char *p, int *pos) { int vert, i; enum tbl_cellt c; /* Handle vertical lines. */ for (vert = 0; '|' == p[*pos]; ++*pos) vert++; while (' ' == p[*pos]) (*pos)++; /* Parse the column position (`c', `l', `r', ...). */ for (i = 0; i < KEYS_MAX; i++) if (tolower((unsigned char)p[*pos]) == keys[i].name) break; if (KEYS_MAX == i) { mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL); return(0); } c = keys[i].key; /* * If a span cell is found first, raise a warning and abort the * parse. If a span cell is found and the last layout element * isn't a "normal" layout, bail. * * FIXME: recover from this somehow? */ if (TBL_CELL_SPAN == c) { if (NULL == rp->first) { mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL); return(0); } else if (rp->last) switch (rp->last->pos) { case (TBL_CELL_HORIZ): case (TBL_CELL_DHORIZ): mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL); return(0); default: break; } } /* * If a vertical spanner is found, we may not be in the first * row. */ if (TBL_CELL_DOWN == c && rp == tbl->first_row) { mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos, NULL); return(0); } (*pos)++; /* Disallow adjacent spacers. */ if (vert > 2) { mandoc_msg(MANDOCERR_TBLLAYOUT, tbl->parse, ln, *pos - 1, NULL); return(0); } /* Allocate cell then parse its modifiers. */ return(mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos)); }