/** * @brief Insert a string in the string table * @param s The string to insert. * @return the pointer to ther string in the string table. */ char * insert_str_c(char * s){ char *without = s; char * format_position = strstr(without, "\\n"); while (format_position) { *format_position = '\n'; ++format_position; memmove(format_position, format_position+1, strlen(format_position+1)+1); format_position = strstr(without, "\\n"); } char * p_on_table = get_str_c(without); if (!p_on_table){ int pos = hash_str_c(without); Str_c_node * new_node = (Str_c_node *)newmem(sizeof(Str_c_node)); new_node->string = (char*)newmem(((int)strlen(without)+1) * sizeof(char)); strcpy(new_node->string, without); p_on_table = new_node->string; new_node->next = str_const_table[pos]; str_const_table[pos] = new_node; } return p_on_table; }
/*Controlla la semantica della write e ne ritorna il codice*/ Code write_stat(Pnode write_stat_node){ //Imposto le due parti del nodo Pnode specifier_node = write_stat_node->child; Pnode expr_node = write_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code write_stat_code; //Calcolo il codice di specifier Pschema schema_specifier = (Pschema) newmem(sizeof(Schema)); Code specifier_code = specifier(specifier_node,schema_specifier); //Controllo che non ci siano errori semantici //Controllo che il tipo di specifier sia corretto if (schema_specifier->type != STRING && schema_specifier->type != NIHIL) semerror(write_stat_node,"Expected string type"); //Genero il codice di write_stat //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //La sintassi della write dipende dalla presenza dello specifier if (specifier_node->child == NULL) write_stat_code = appcode(expr_code,make_print_fprint(T_PRINT,get_format(*schema_expr))); else write_stat_code = concode(expr_code,specifier_code,make_print_fprint(T_FPRINT,get_format(*schema_expr)),endcode()); return write_stat_code; }
/** * @brief Allocate memory for the odescr adn put it on top of the ostack. * * If necessary expand the ostack. * * @return a pointer to the top of ostack. */ Odescr * push_ostack(){ Odescr **old_ostack; int i; if(op == osize) { old_ostack = ostack; ostack = (Odescr**) newmem(sizeof(Odescr*)*(osize + OSTACK_UNIT)); for(i = 0; i < osize; i++) ostack[i] = old_ostack[i]; freemem((char*)old_ostack, sizeof(Odescr*)*osize); osize += OSTACK_UNIT; } return (ostack[op++] = (Odescr*)newmem(sizeof(Odescr))); }
/** * @brief This function allocates memory for the adescr and puts it on top of the astack. * * If necessary it expands the astack. * * @return a pointer to the top of astack. */ Adescr * push_astack(){ Adescr **old_astack; int i; if(ap == asize) { old_astack = astack; astack = (Adescr**) newmem(sizeof(Adescr*)*(asize + ASTACK_UNIT)); for(i = 0; i < asize; i++) astack[i] = old_astack[i]; freemem((char*)old_astack, sizeof(Adescr*)*asize); asize += ASTACK_UNIT; } return (astack[ap++] = (Adescr*)newmem(sizeof(Adescr))); }
void exec_push(int num_objects, int return_address){ Adescr *pa = push_astack(); pa->num_objects = num_objects; pa->num_inited = 0; pa->return_address = return_address; pa->objects = (Odescr *)newmem(num_objects * sizeof(Odescr)); }
/*Controlla la semantica del nodo while e ne restituisce il codice*/ Code while_stat(Pnode while_stat_node){ //Imposto le due parti del nodo Pnode expr_node = while_stat_node->child; Pnode stat_list_node = while_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code while_stat_code; //La generazione dell'ambiente viene fatta all'interno della funzione stat_list //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //Controllo i vincoli semantici if (schema_expr->type!=BOOLEAN) semerror(expr_node,"Expected boolean type"); //Genero il codice di stat_list Code stat_list_code = stat_list(stat_list_node); //Calcolo gli offset int exit = stat_list_code.size + 2; int up = -(expr_code.size + stat_list_code.size + 1); //Genero il codice di while_stat while_stat_code = concode(expr_code,makecode1(T_SKIPF,exit),stat_list_code,makecode1(T_SKIP,up),endcode()); return while_stat_code; }
/*Controlla i vincoli semantici dell'assegnamento e ne ritorna il codice*/ Code assign_stat(Pnode assign_stat_node){ #ifdef DEBUG_ASSIGN_STAT printf("ASSIGN_STAT - enter\n"); #endif //Imposto le due parti del nodo Pnode id_node = assign_stat_node->child; Pnode expr_node = assign_stat_node->child->brother; //Definisco la variabile che contiene il codice da ritornare Code assign_stat_code ; //Controllo i vincoli semantici //Visibilità del nome if (lookup(valname(id_node))==NULL) semerror(id_node,"Undefined variable"); //Compatibilità degli schemi Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); Psymbol symbol = lookup(valname(id_node)); if (!type_equal((symbol->schema),*(schema_expr))) semerror(assign_stat_node,"Incompatible types"); //Genero il codice assign_stat_code = appcode(expr_code,makecode1(T_STO,symbol->oid)); #ifdef DEBUG_ASSIGN_STAT printf("ASSIGN_STAT - exit\n"); #endif return assign_stat_code; }
void exec_news(int size){ Odescr *po; po = &top_astack()->objects[top_astack()->num_inited++]; po->mode = STA; po->size = size; po->inst.sval = (char *)newmem(size * sizeof(char)); }
/** * @brief Increment the istack with the size and return the new top. * * If necessary expand the istack. * * @param size how much increment the istack. * @return a pointer to the top of istack. */ char * push_istack(int size){ char *old_istack; int i, n; if(ip+size >= isize) { n = size/ISTACK_UNIT; old_istack = istack; istack = newmem(isize + ISTACK_UNIT); istack = newmem(isize + (n+1) * ISTACK_UNIT); for(i = 0; i < isize; i++) istack[i] = old_istack[i]; freemem(old_istack, isize); isize += ISTACK_UNIT; isize += (n+1) * ISTACK_UNIT; } ip+=size; return &(istack[ip-size]); }
/** * @brief This functin opens the input file and do the initial memory allocation of data structures. * @param input the s_code filename. */ void start_machine(char * input) { str_const_table = (Str_c_node **)newmem(sizeof(Str_c_node*)*STR_CONST_DIM); FILE *input_file = fopen(input, "r"); if (!input_file){ machine_error("ERRORE nel caricamento del file"); } load_scode(input_file); fclose (input_file); pc = ap = op = ip = 0; astack = (Adescr**)newmem(sizeof(Adescr*)*ASTACK_UNIT); asize = ASTACK_UNIT; ostack = (Odescr**)newmem(sizeof(Odescr*)*OSTACK_UNIT); osize = OSTACK_UNIT; istack = (char*)newmem(ISTACK_UNIT); isize = ISTACK_UNIT; }
Tstat *newstat(Operator op) { Tstat *pstat; pstat = (Tstat*) newmem(sizeof(Tstat)); pstat->address = 0; pstat->op = op; pstat->next = NULL; return pstat; }
void exec_sil(int field_size){ Odescr *op = pop_tstack(); Odescr *op2 = push_tstack(); op2->size = field_size; op2->mode = STA; op2->inst.sval = newmem(op2->size); memcpy(op2->inst.sval, op->inst.sval, op2->size); // only dealloc the object and not the inst freemem((char*)op, sizeof(Odescr)); }
char *update_lextab(char *s) { int index; Pname p; char *ps; index = hash_function(s); for(p = lextab[index]; p != NULL; p = p->next) { if(strcmp(p->name, s) == 0) return(p->name); } ps = newmem(strlen(s)+1); strcpy(ps, s); p = lextab[index]; lextab[index] = (Pname) newmem(sizeof(Name)); lextab[index]->name = ps; lextab[index]->next = p; return(lextab[index]->name); }
Pname id_list(Pnode p, int* quanti) { if (p != NULL) { Pname lista = (Pname)newmem(sizeof(Name)); lista->name = p->value.sval; (*quanti)++; lista->next = id_list(p->brother, quanti); return lista; } else return NULL; }
void exec_cat(int num_fields, int size){ int size_done = 0; int fields_done = 0; char *instance = newmem(size); while(fields_done < num_fields){ Odescr *op = pop_tstack(); int dest_start = size - size_done - op->size; // if there is an error reverse it, starting from 0 -- using size_done as index if(op->mode == EMB){ switch(op->size){ case sizeof(char): instance[dest_start] = op->inst.cval; break; case sizeof(int): *((int *)(instance+dest_start)) = op->inst.ival; break; case sizeof(char *):{ char *actual_address = instance+dest_start; char** act = (char **)actual_address; act[0] = op->inst.sval; //printf("%s %s\n",op->inst.sval, act[0]); //printf("%p %s\n%p %s\n\n", act[0],act[0], op->inst.sval,op->inst.sval); break; } default: machine_error("Unknown type for op->size"); break; } } else{ memcpy(instance + dest_start, op->inst.sval, op->size); } size_done += op->size; fields_done++; free_odescr(op); } Odescr *op2 = push_tstack(); op2->size = size; op2->mode = STA; op2->inst.sval = instance; // this allocates space on the instance stack and than copies byte by byte all the elements on the stack // taking them to the tstack (?) /* TSTACK: expr1_res expr2_res ... INSTANCE -> expr1_res, expr2_res, ... creates a single record on the tstack with SIZE, STA and with the pointer to the allocated instance */ }
Psymbol insert(Pschema schema) { int index; Psymbol psymbol; index = hash_function(schema->name); psymbol = symtab[index]; symtab[index] = (Psymbol) newmem(sizeof(Symbol)); symtab[index]->oid = oid_counter++; symtab[index]->size = get_size(schema); symtab[index]->schema = schema; symtab[index]->next = psymbol; return(symtab[index]); }
/*Riceve la testa della id_list e ritorna una lista di nomi più il numero di id presenti nella lista*/ Pname id_list(Pnode id_list_head, int *length){ Pname head_name,id_name,prev_name; //Creo head_name e ne imposto i campi head_name = (Pname) newmem(sizeof(Name)); head_name->name = valname(id_list_head); head_name->next = NULL; //Imposto il numero di id a 1 *length = 1; //Punto al secondo id Pnode id = id_list_head->brother; //Salvo l'indirizzo di prev_name prev_name = head_name; while(id != NULL) { //Creo un nodo pname id_name = (Pname) newmem(sizeof(Name)); //Imposto valname e next id_name->name = valname(id); id_name->next = NULL; //Imposto il puntatore al prossimo elemento della lista prev_name->next = id_name; //Incremento il numero di id *length = *length + 1; //Passo all'id successivo id = id->brother; //Prev_name punta all'ultimo nome nella lista prev_name = id_name; } return head_name; }
/*Ritorna lo schema e imposta il tipo nel campo type di schema*/ Pschema atomic_type(Pnode atomic_type_node){ #ifdef DEBUG_ATOMIC_TYPE printf( "ATOMIC_TYPE_NODE - enter\n"); #endif //Creo lo schema Pschema schema = (Pschema) newmem(sizeof(Schema)); //Imposto tutti i campi a null schema->name = NULL; schema->next = NULL; //Imposto il type schema->type = qualifier(atomic_type_node); #ifdef DEBUG_ATOMIC_TYPE printf( "ATOMIC_TYPE_NODE - exit\n"); #endif return schema; }
/*Genera lo schema della tupla e ritorna il codice*/ Code tuple_const(Pnode tuple_const_node,Pschema schema){ //Non ci sono vincoli semantici #ifdef DEBUG_TUPLE_CONST printf( "TUPLE_CONST - enter\n"); #endif //Preparo il codice della tupla Code tuple_const_code; tuple_const_code.head = NULL; //Punto al primo elemento della tupla Pnode atomic_const_node = tuple_const_node->child; //Preparo la variabile che contiene il codice dell'id Code atomic_const_code; Pschema prev_schema = schema; do{ //Calcolo il codice e lo schema della prima costante switch(atomic_const_node->type){ case (N_INTCONST): atomic_const_code = makecode1(T_IATTR,qualifier(atomic_const_node)); prev_schema->type = INTEGER; break; case (N_BOOLCONST): atomic_const_code = makecode1(T_IATTR,qualifier(atomic_const_node)); prev_schema->type = BOOLEAN; break; case (N_STRCONST): atomic_const_code = make_sattr(valname(atomic_const_node)); prev_schema->type = STRING; break; } //Appendo il codice della costante al codice della tupla tuple_const_code = appcode(tuple_const_code,atomic_const_code); //Passo al fratello atomic_const_node = atomic_const_node->brother; //Creo un nuovo schema if (atomic_const_node!=NULL){ Pschema newSchema = (Pschema) newmem(sizeof(Schema)); prev_schema->next = newSchema; prev_schema = prev_schema->next; } }while(atomic_const_node!=NULL); #ifdef DEBUG_TUPLE_CONST printf( "TUPLE_CONST - exit\n"); #endif return tuple_const_code; }
/*Controlla la semantica del nodo if e ne ritorna il codice*/ Code if_stat(Pnode if_stat_node){ #ifdef DEBUG_IF_STAT printf("IF_STAT - enter\n"); #endif //Imposto le tre parti del nodo Pnode expr_node = if_stat_node->child; Pnode then_node = if_stat_node->child->brother; Pnode else_node = if_stat_node->child->brother->brother; //Definisco la variabile che contiene il codice da ritornare Code if_stat_code ; //La generazione dell'ambiente viene fatta all'interno della funzione stat_list //Genero il codice di expr Pschema schema_expr = (Pschema) newmem(sizeof(Schema)); Code expr_code = expr(expr_node,schema_expr); //Controllo i vincoli semantici if (schema_expr->type!=BOOLEAN) semerror(expr_node,"Expected boolean type"); //Genero il codice di then_node Code then_code = stat_list(then_node); if (else_node==NULL){//if then endif //Calcolo l'offset int offset = then_code.size + 1; //Genero il codice di if_stat if_stat_code = concode(expr_code,makecode1(T_SKIPF,offset),then_code,endcode()); } else {//if then else //Genero il codice di else_node Code else_code = stat_list(else_node); //Calcolo gli offset int offset_then = then_code.size + 2; int offset_else = else_code.size + 1; //Genero il codice di if_stat if_stat_code = concode(expr_code,makecode1(T_SKIPF,offset_then),then_code,makecode1(T_SKIP,offset_else),else_code,endcode()); } #ifdef DEBUG_IF_STAT printf("IF_STAT - exit\n"); #endif return if_stat_code; }
/* Ritorna lo schema del table_type. */ Pschema table_type(Pnode type_node){ #ifdef DEBUG_TABLE_TYPE printf( "TABLE_TYPE - enter\n"); #endif //Creo lo schema Pschema schema = (Pschema) newmem(sizeof(Schema)); schema->name = NULL; //Imposto il type (che sarà TABLE) schema->type = qualifier(type_node); //Genero la lista di attributi schema->next = attr_list(type_node->child); #ifdef DEBUG_TABLE_TYPE printf( "TABLE_TYPE - ok attr_list definition\n"); #endif return schema; }
void* allocmem(size_t size) { void* result = safe_alloc(size); { long h; { long i; h=hash(result); for (i=0; i<maxptrs; i++) if (ptr[h]==NULL) break; else if (++h>=maxptrs) h=0; if (i==maxptrs) { /*error("Object table overflow (%ld). Try increasing 'maxobjects'.\n" ,chunks); */ /* we're just going to dynamically grow the object table */ newmem(3*maxptrs/2); /* increase maxptrs by 50% */ free(result); return allocmem(size); /* safe to call again now */ } } ignore_intr(); /* don't interrupt while updating |ptr| */ ptr[h]=result; ++chunks; allow_intr(); } return result; }
char *get_format(Pschema schema) { char *format; char *attr_name, *atomic_type; Boolean first = TRUE; format = (char*) newmem(MAXFORMAT); switch(schema->type) { case INTEGER: sprintf(format, "i"); break; case STRING: sprintf(format, "s"); break; case BOOLEAN: sprintf(format, "b"); break; case TABLE: sprintf(format, "("); for(schema = schema->next; schema; schema = schema->next) { attr_name = (schema->name ? schema->name : "?"); atomic_type = (schema->type == INTEGER ? "i" : (schema->type == STRING ? "s" : "b")); if(first == FALSE) strcat(format, ","); sprintf(&format[strlen(format)], "%s:%s", attr_name, atomic_type); first = FALSE; } strcat(format, ")"); break; default: syserror("get_format()"); } return(format); }
/*Controlla la semantica della read e ritorna il codice della read*/ Code read_stat(Pnode read_stat_node){ #ifdef DEBUG_READ_STAT printf("READ_STAT - enter\n"); #endif //Imposto le due parti del nodo Pnode specifier_node = read_stat_node->child; Pnode id_node = read_stat_node->child->brother; //Definisco il codice del nodo Code read_stat_code; read_stat_code.head = NULL; //Calcolo il codice di specifier Pschema schema_specifier = (Pschema) newmem(sizeof(Schema)); Code specifier_code = specifier(specifier_node,schema_specifier); //Controllo che non ci siano errori semantici //Controllo che il tipo di specifier sia corretto if ((schema_specifier->type != STRING) && (schema_specifier->type != NIHIL)) semerror(read_stat_node,"Expected string type"); //Controllo che il nome dell'id sia visibile if (lookup(valname(id_node))==NULL) semerror(id_node,"Variable not defined"); //Genero il codice di readstat //La sintassi della read dipende dalla presenza dello specifier Psymbol symbol = lookup(valname(id_node)); if (specifier_node->child == NULL) read_stat_code = make_get_fget(T_GET,symbol->oid,get_format((symbol->schema))); else read_stat_code = appcode(specifier_code,make_get_fget(T_FGET,symbol->oid,get_format((symbol->schema)))); #ifdef DEBUG_READ_STAT printf("READ_STAT - exit\n"); #endif return read_stat_code; }