/* Libera el registro AL ocupado usando la variable parametro y lo retorna */ Element *free_AL(Element *variable) { Stack *pila_aux = (Stack *)0; Element *elem_aux = (Element *)malloc(sizeof(Element)); Element *ret = (Element *)malloc(sizeof(Element)); /* Busco el registro AL ocupado para liberarlo */ spop(&pila, (void *)&elem_aux); while (elem_aux->code != REGISTRO || (elem_aux->code == REGISTRO && elem_aux->value != 0)) { spush(&pila_aux, (void *)elem_aux); spop(&pila, (void *)&elem_aux); } /* Vuelco el contenido del registro a liberar en la variable parametro */ fprintf(output_fd, "\t\tMOV\t_%s, %s\n", variable->name, elem_aux->name); /* Apilo la variable en lugar del registro y * * guardo en la variable el registro a retornar */ spush(&pila, (void *)variable); ret = load_register(0); /* Apilo nuevamente los demas operandos sacados de la pila */ while (pila_aux != (Stack *)0) { spop(&pila_aux, (void *)&elem_aux); spush(&pila, (void *)elem_aux); } return ret; }
/* Libera cualquier registro ocupado usando la variable parametro y lo retorna */ Element *free_any_notA(Element *variable) { Stack *pila_aux; Element *elem_aux = (Element *)malloc(sizeof(Element)); Element *ret = (Element *)malloc(sizeof(Element)); /* Busco un registro ocupado que no sea ni AH ni AL, para liberarlo */ spop(&pila, (void *)&elem_aux); while (elem_aux->code != REGISTRO || (elem_aux->code == REGISTRO && (elem_aux->value == 0 || elem_aux->value == 1))) { spush(&pila_aux, (void *)elem_aux); spop(&pila, (void *)&elem_aux); } /* Vuelco el contenido del registro a liberar en la variable parametro */ fprintf(output_fd, "\t\tMOV\t_%s, %s\n", variable->name, elem_aux->name); /* Apilo la variable en lugar del registro y * * guardo en la variable el registro a retornar */ spush(&pila, (void *)variable); ret->code = REGISTRO; strcpy(ret->name, elem_aux->name); ret->value = elem_aux->value; /* Apilo nuevamente los demas operandos sacados de la pila */ spop(&pila_aux, (void *)&elem_aux); while (elem_aux != (Element *)0) { spush(&pila, (void *)elem_aux); spop(&pila_aux, (void *)&elem_aux); } return ret; }
void generar_or(Element *obj) { Element *operando1 = (Element *)malloc(sizeof(Element)); Element *operando2 = (Element *)malloc(sizeof(Element)); spop(&pila, (void *)&operando2); spop(&pila, (void *)&operando1); if (operando1->code == REGISTRO) { if (operando2->code == REGISTRO) { //Registro-Registro fprintf(output_fd, "\t\tOR\t%s, %s\n", operando2->name, operando1->name); state[operando1->value] = 0; /*Libero el registro*/ spush(&pila, (void *)operando2); } else { //Registro-Operando if (operando2->code == IDENTIFICADOR) fprintf(output_fd, "\t\tOR\t%s, _%s\n", operando1->name, operando2->name); else fprintf(output_fd, "\t\tOR\t%s, %d\n", operando1->name, operando2->value); spush(&pila, (void *)operando1); } } else { if (operando2->code == REGISTRO) { //Operando-Registro if (operando1->code == IDENTIFICADOR) fprintf(output_fd, "\t\tOR\t%s, _%s\n", operando2->name, operando1->name); else fprintf(output_fd, "\t\tOR\t%s, %d\n", operando2->name, operando1->value); spush(&pila, (void *)operando2); } else { //Operando-Operando Element *op_aux = get_free(); if (operando1->code == IDENTIFICADOR) { if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando1->name); fprintf(output_fd, "\t\tOR\t%s, _%s\n", op_aux->name, operando2->name); } else { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando1->name); fprintf(output_fd, "\t\tOR\t%s, %d\n", op_aux->name, operando2->value); } } else { if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando1->value); fprintf(output_fd, "\t\tOR\t%s, _%s\n", op_aux->name, operando2->name); } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando1->value); fprintf(output_fd, "\t\tOR\t%s, %d\n", op_aux->name, operando2->value); } } spush(&pila, (void *)op_aux); state[op_aux->value] = 1; } } }
err_t connect_cb(void *arg, struct tcp_pcb *newpcb, err_t err) { cell *up = callback_up; if (!connect_forth_cb) { return 0; } spush((cell)err, up); spush((cell)newpcb, up); spush(arg, up); return execute_xt_pop(connect_forth_cb, up); }
void gethostbyname_cb(char *name, struct ip_addr *ipaddr, void *arg) { cell *up = callback_up; if (!gethostbyname_forth_cb) { return; } SWITCH_STACKS("gh"); spush(arg, up); spush((cell)ipaddr, up); spush((cell)name, up); execute_xt(gethostbyname_forth_cb, up); RESTORE_STACKS; }
void err_cb(void *arg, err_t err) { cell *up = callback_up; if (!err_forth_cb) { return; } SWITCH_STACKS("err"); spush((cell)err, up); spush(arg, up); execute_xt(err_forth_cb, up); RESTORE_STACKS; }
err_t poll_cb(void *arg, struct tcp_pcb *tpcb) { cell *up = callback_up; if (!poll_forth_cb) { return 0; } SWITCH_STACKS("poll"); spush((cell)tpcb, up); spush(arg, up); err_t retval = execute_xt_pop(poll_forth_cb, up); RESTORE_STACKS; return retval; }
err_t sent_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) { cell *up = callback_up; if (!sent_forth_cb) { return 0; } SWITCH_STACKS("sent"); spush((cell)len, up); spush((cell)tpcb, up); spush(arg, up); err_t retval = execute_xt_pop(sent_forth_cb, up); RESTORE_STACKS; return retval; }
err_t accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err) { cell *up = callback_up; if (!accept_forth_cb) { return 0; } SWITCH_STACKS("ac"); spush((cell)err, up); spush((cell)newpcb, up); spush(arg, up); err_t retval = execute_xt_pop(accept_forth_cb, up); RESTORE_STACKS; return retval; }
err_t continuation_cb(void *arg, struct tcp_pcb *tpcb, u16_t len) { cell *up = callback_up; if (!sent_forth_cb) { return 0; } SWITCH_STACKS("cont"); spush((cell)len, up); spush((cell)tpcb, up); spush(arg, up); err_t retval = inner_interpreter(up); RESTORE_STACKS; return retval; }
void parsearglist(void) { vpush((numvar) arg); // save base of current argblock #if defined(STRING_POOL) vpush((numvar) stringPool); // save stringPool base for later release strpush(idbuf); // save called function's name as arg[-1] #endif numvar *newarg = &vstack[vsptr]; // move global arg pointer to base of new block vpush(0); // initialize new arg(0) (a/k/a argc) to 0 if (sym == s_lparen) { getsym(); // eat arglist '(' while ((sym != s_rparen) && (sym != s_eof)) { #if defined(STRING_POOL) if (sym == s_quote) { vpush((numvar) stringPool); // push the string pointer parsestring(&spush); // parse it into the pool spush(0); // and terminate it getsym(); // eat closing " } else #endif vpush(getnum()); // push the value newarg[0]++; // bump the count if (sym == s_comma) getsym(); // eat arglist ',' and go around else break; } if (sym == s_rparen) getsym(); // eat the ')' else expected(M_rparen); } arg = newarg; // activate new argument frame }
int _ol_grow_and_rehash_db(ol_database *db) { int i; ol_bucket *bucket; ol_bucket **tmp_hashes = NULL; size_t to_alloc = db->cur_ht_size * 2; debug("Growing DB to %zu bytes.", to_alloc); tmp_hashes = calloc(1, to_alloc); check_mem(tmp_hashes); struct ol_stack *orphans = NULL; orphans = malloc(sizeof(struct ol_stack)); check_mem(orphans); orphans->next = NULL; orphans->data = NULL; int orphans_found = 0; int iterations = ol_ht_bucket_max(db->cur_ht_size); for (i = 0; i < iterations; i++) { bucket = db->hashes[i]; if (bucket != NULL) { if (bucket->next != NULL) { ol_bucket *tmp_bucket = bucket; do { spush(&orphans, tmp_bucket->next); ol_bucket *next = tmp_bucket->next; tmp_bucket->next = NULL; tmp_bucket = next; orphans_found++; } while (tmp_bucket->next != NULL); } /* Rehash the bucket itself. */ _ol_rehash_insert_bucket(tmp_hashes, to_alloc, bucket); } } /* Take care of our orphans */ ol_log_msg(LOG_INFO, "Have %i orphans to take care of.", orphans_found); do { ol_bucket *rebucket = spop(&orphans); _ol_rehash_insert_bucket(tmp_hashes, to_alloc, rebucket); orphans_found--; } while (orphans->next != NULL); ol_log_msg(LOG_INFO, "We now have %i orphans not accounted for.", orphans_found); free(orphans); free(db->hashes); db->hashes = tmp_hashes; db->cur_ht_size = to_alloc; debug("Current hash table size is now: %zu bytes.", to_alloc); return 0; error: if (tmp_hashes != NULL) free(tmp_hashes); return -1; }
void generar_comparacion(Element *obj, char *etiqueta) { Element *operando1 = (Element *)malloc(sizeof(Element)); Element *operando2 = (Element *)malloc(sizeof(Element)); spop(&pila, (void *)&operando2); spop(&pila, (void *)&operando1); if (operando1->code == REGISTRO) { if (operando2->code == REGISTRO) { //Registro-Registro fprintf(output_fd, "\t\tCMP\t%s, %s\n", operando1->name, operando2->name); } else { //Registro-Operando if (operando2->code == IDENTIFICADOR) fprintf(output_fd, "\t\tCMP\t%s, _%s\n", operando1->name, operando2->name); else fprintf(output_fd, "\t\tCMP\t%s, %d\n", operando1->name, operando2->value); } } else { Element *op_aux2 = get_free(state); if (operando2->code == REGISTRO) { //Operando-Registro if (operando1->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux2->name, operando1->name); fprintf(output_fd, "\t\tCMP\t%s, %s\n", operando2->name, op_aux2->name); } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux2->name, operando1->value); fprintf(output_fd, "\t\tCMP\t%s, %s\n", operando2->name, op_aux2->name); } } else { //Operando-Operando if (operando1->code == IDENTIFICADOR) { if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux2->name, operando1->name); fprintf(output_fd, "\t\tCMP\t%s, _%s\n", op_aux2->name, operando2->name); } else { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux2->name, operando1->name); fprintf(output_fd, "\t\tCMP\t%s, %d\n", op_aux2->name, operando2->value); } } else { if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux2->name, operando1->value); fprintf(output_fd, "\t\tCMP\t%s, _%s\n", op_aux2->name, operando2->name); } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux2->name, operando1->value); fprintf(output_fd, "\t\tCMP\t%s, %d\n", op_aux2->name, operando2->value); } } } } Element *op_aux = get_free(); state[op_aux->value] = 1; spush(&pila, (void *)op_aux); fprintf(output_fd, "\t\t%s\tLABEL00%d\n", etiqueta, labelnumber); fprintf(output_fd, "\t\tMOV\t%s, 0\n", op_aux->name); fprintf(output_fd, "\t\tJMP\tLABEL00%d\n", labelnumber+1); fprintf(output_fd, "\tLABEL00%d:\n\t\tMOV\t%s, 1\n", labelnumber, op_aux->name); labelnumber++; fprintf(output_fd, "\tLABEL00%d:\n", labelnumber); labelnumber++; }
err_t recv_cb(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { cell *up = callback_up; if (!recv_forth_cb) { return 0; } SWITCH_STACKS("recv"); spush((cell)err, up); spush((cell)p, up); spush((cell)tpcb, up); spush(arg, up); err_t retval = execute_xt_pop(recv_forth_cb, up); RESTORE_STACKS; return retval; }
void generar_not(Element *obj) { Element *operando = (Element *)malloc(sizeof(Element)); spop(&pila, (void *)&operando); if (operando->code == REGISTRO) { fprintf(output_fd, "\t\tNOT\t%s\n", operando->name); spush(&pila, (void *)operando); } else { Element *op_aux = get_free(); if (operando->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando->name); } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando->value); } fprintf(output_fd, "\t\tNOT\t%s\n", op_aux->name); state[op_aux->value] = 1; spush(&pila, (void *)op_aux); } }
void stack_init (void) { what_are_we_in_stk = more_chars (); wawi_push (0); if ((while_stack = more_whiles ()) == NULL) { perror ("no more whiles"); return; } switch_stack = more_switches (); wpush (NULL); in_while--; wawi_stk_ptr--; spush (NULL); in_switch--; wawi_stk_ptr--; }
/* Generar el codigo con el algoritmo de seguimiento de registros */ void generate() { Element *obj; extern Symbol *symbol_table; fprintf(output_fd, ".MODEL SMALL\n.CODE\n\t\tORG\t100h\n__MAIN:\t\t\t\t\t; Cuerpo\n"); while (element_stack != (Element *)0) { obj = pop(); if (is_operand(obj)) { spush(&pila, (void *)obj); } else { switch (obj->code) { case '+': generar_suma(obj); break; case '-': generar_resta(obj); break; case '*': generar_multiplicacion(obj); break; case '/': generar_division(obj); break; case '=': generar_asignacion(obj); break; case '!': generar_not(obj); break; case AND: generar_and(obj); break; case OR: generar_or(obj); break; case MENOR_IGUAL: generar_comparacion(obj, "JBE"); break; case MAYOR_IGUAL: generar_comparacion(obj, "JAE"); break; case DISTINTO: generar_comparacion(obj, "JNE"); break; case IGUAL: generar_comparacion(obj, "JE"); break; case '>': generar_comparacion(obj, "JA"); break; case '<': generar_comparacion(obj, "JB"); break; case BF: generar_BF(obj); break; case BI: generar_BI(obj); break; case CL: create_label(obj); break; } } } // Rutina de fin de programa fprintf(output_fd, "\tLABEL FIN:\t\t\t; Fin de programa\n"); fprintf(output_fd, "\t\tMOV\tAH, 00h\n"); fprintf(output_fd, "\t\tINT\t21h\n"); /* Generar las declaraciones de variables a partir de la tabla de simbolos */ Symbol *sym; fprintf(output_fd, "\n\n\t\tORG\t1000h\t\t; Definicion de variables\n"); while (symbol_table != (Symbol *)0) { sym = get_first(); fprintf(output_fd, "\t\t_%s", sym->name); fprintf(output_fd, "\tDB\t0\n"); } // Cierre de __MAIN fprintf(output_fd, "END __MAIN\n"); }
void generar_division(Element *obj) { Element *operando1 = (Element *)malloc(sizeof(Element)); Element *operando2 = (Element *)malloc(sizeof(Element)); spop(&pila, (void *)&operando2); spop(&pila, (void *)&operando1); if (operando1->code == REGISTRO && operando1->value == 0) { //operando1 ya esta en AL, pasar operando2 a un registro distinto de AH, si es necesario ; } else { if (operando2->code == REGISTRO && operando2->value == 0) { //operando2 esta en AL, pasar a operando2 a un registro distinto y pasar operando1 a AL Element *op_aux = get_free_notA(); fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando2->name); fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando2->name); operando2 = op_aux; state[operando2->value] = 1; Element *op_aux2 = get_free_AL(); if (operando1->code == REGISTRO) { fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux2->name, operando1->name); state[operando1->value] = 0; operando1 = op_aux2; } else { if (operando1->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux2->name, operando1->name); operando1 = op_aux2; } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux2->name, operando1->value); operando1 = op_aux2; } } } else { //ninguno esta en AL. Pasar operando1 a AL y operando2 a un registro distinto de AH, si es necesario Element *op_aux = get_free_AL(); if (operando1->code == REGISTRO) { fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando1->name); state[operando1->value] = 0; operando1 = op_aux; } else { if (operando1->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando1->name); operando1 = op_aux; } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando1->value); operando1 = op_aux; } } state[0] = 1; } } if (operando2->code == REGISTRO) { if (operando2->value == 1) { //esta en AH, moverlo a otro registro libre. Element *op_aux = get_free_notA(); fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando2->name); operando2 = op_aux; state[operando2->value] = 1; } else { //esta en otro registro. No hacer nada. ; } } else { //conseguir un registro libre distinto de AH y mover operando2 alli. Element *op_aux = get_free_notA(); if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando2->name); operando2 = op_aux; } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando2->value); operando2 = op_aux; } state[operando2->value] = 1; } state[1] = 0; // Chequear por división por cero fprintf(output_fd, "\t\tJNZ\tLABEL00%d\t; Chequeo de división por cero\n", labelnumber); incluir_recuperacion_div_cero(operando2); fprintf(output_fd, "\tLABEL00%d:\n\t\tCBW\n", labelnumber); labelnumber++; //A esta altura, operando1 es AL y operando2 es otro registro distinto de AH fprintf(output_fd, "\t\tIDIV\t%s\n", operando2->name); state[operando2->value] = 0; /*Libero el registro*/ //Apilo AL, el cociente spush(&pila, (void *)operando1); }
void lpush() { spush(); spush(); }
// push a string into the string pool void strpush(char *ptr) { while (*ptr) spush(*ptr++); spush(0); }
static inline char * tparam_internal(const char *string, int *dataptr) { #define NUM_VARS 26 char *p_is_s[9]; int param[9]; int lastpop; int popcount; int number; int len; int level; int x, y; int i; int len2; register const char *cp; static int len_fmt = MAX_FORMAT_LEN; static char dummy[] = ""; static char format[MAX_FORMAT_LEN]; static int dynamic_var[NUM_VARS]; static int static_vars[NUM_VARS]; out_used = 0; if (string == NULL) return NULL; if ((len2 = grub_strlen(string)) > len_fmt) { return NULL; } /* * Find the highest parameter-number referred to in the format string. * Use this value to limit the number of arguments copied from the * variable-length argument list. */ number = 0; lastpop = -1; popcount = 0; grub_memset(p_is_s, 0, sizeof(p_is_s)); /* * Analyze the string to see how many parameters we need from the varargs * list, and what their types are. We will only accept string parameters * if they appear as a %l or %s format following an explicit parameter * reference (e.g., %p2%s). All other parameters are numbers. * * 'number' counts coarsely the number of pop's we see in the string, and * 'popcount' shows the highest parameter number in the string. We would * like to simply use the latter count, but if we are reading termcap * strings, there may be cases that we cannot see the explicit parameter * numbers. */ for (cp = string; (cp - string) < (int) len2;) { if (*cp == '%') { cp++; cp = parse_format(cp, format, &len); switch (*cp) { default: break; case 'd': /* FALLTHRU */ case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ number++; lastpop = -1; break; case 'l': case 's': if (lastpop > 0) p_is_s[lastpop - 1] = dummy; ++number; break; case 'p': cp++; i = (*cp - '0'); if (i >= 0 && i <= 9) { lastpop = i; if (lastpop > popcount) popcount = lastpop; } break; case 'P': case 'g': cp++; break; case '\'': cp += 2; lastpop = -1; break; case '{': cp++; while (*cp >= '0' && *cp <= '9') { cp++; } break; case '+': case '-': case '*': case '/': case 'm': case 'A': case 'O': case '&': case '|': case '^': case '=': case '<': case '>': case '!': case '~': lastpop = -1; number += 2; break; case 'i': lastpop = -1; if (popcount < 2) popcount = 2; break; } } if (*cp != '\0') cp++; } if (number > 9) number = 9; for (i = 0; i < max(popcount, number); i++) { /* * A few caps (such as plab_norm) have string-valued parms. * We'll have to assume that the caller knows the difference, since * a char* and an int may not be the same size on the stack. */ if (p_is_s[i] != 0) { p_is_s[i] = (char *)(*(dataptr++)); } else { param[i] = (int)(*(dataptr++)); } } /* * This is a termcap compatibility hack. If there are no explicit pop * operations in the string, load the stack in such a way that * successive pops will grab successive parameters. That will make * the expansion of (for example) \E[%d;%dH work correctly in termcap * style, which means tparam() will expand termcap strings OK. */ stack_ptr = 0; if (popcount == 0) { popcount = number; for (i = number - 1; i >= 0; i--) npush(param[i]); } while (*string) { /* skip delay timings */ if (*string == '$' && *(string + 1) == '<') { while( *string && *string != '>') string++; if ( *string == '>' ) string++; } else if ( *string == '%') { string++; string = parse_format(string, format, &len); switch (*string) { default: break; case '%': save_char('%'); break; case 'd': /* FALLTHRU */ case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ save_number(format, npop(), len); break; case 'l': save_number("%d", strlen(spop()), 0); break; case 's': save_text(format, spop(), len); break; case 'p': string++; i = (*string - '1'); if (i >= 0 && i < 9) { if (p_is_s[i]) spush(p_is_s[i]); else npush(param[i]); } break; case 'P': string++; if (isUPPER(*string)) { i = (*string - 'A'); static_vars[i] = npop(); } else if (isLOWER(*string)) { i = (*string - 'a'); dynamic_var[i] = npop(); } break; case 'g': string++; if (isUPPER(*string)) { i = (*string - 'A'); npush(static_vars[i]); } else if (isLOWER(*string)) { i = (*string - 'a'); npush(dynamic_var[i]); } break; case '\'': string++; npush(*string); string++; break; case '{': number = 0; string++; while (*string >= '0' && *string <= '9') { number = number * 10 + *string - '0'; string++; } npush(number); break; case '+': npush(npop() + npop()); break; case '-': y = npop(); x = npop(); npush(x - y); break; case '*': npush(npop() * npop()); break; case '/': y = npop(); x = npop(); npush(y ? (x / y) : 0); break; case 'm': y = npop(); x = npop(); npush(y ? (x % y) : 0); break; case 'A': npush(npop() && npop()); break; case 'O': npush(npop() || npop()); break; case '&': npush(npop() & npop()); break; case '|': npush(npop() | npop()); break; case '^': npush(npop() ^ npop()); break; case '=': y = npop(); x = npop(); npush(x == y); break; case '<': y = npop(); x = npop(); npush(x < y); break; case '>': y = npop(); x = npop(); npush(x > y); break; case '!': npush(!npop()); break; case '~': npush(~npop()); break; case 'i': if (p_is_s[0] == 0) param[0]++; if (p_is_s[1] == 0) param[1]++; break; case '?': break; case 't': x = npop(); if (!x) { /* scan forward for %e or %; at level zero */ string++; level = 0; while (*string) { if (*string == '%') { string++; if (*string == '?') level++; else if (*string == ';') { if (level > 0) level--; else break; } else if (*string == 'e' && level == 0) break; } if (*string) string++; } } break; case 'e': /* scan forward for a %; at level zero */ string++; level = 0; while (*string) { if (*string == '%') { string++; if (*string == '?') level++; else if (*string == ';') { if (level > 0) level--; else break; } } if (*string) string++; } break; case ';': break; } /* endswitch (*string) */ } else { /* endelse (*string == '%') */ save_char(*string); } if (*string == '\0') break; string++; } /* endwhile (*string) */ get_space(1); out_buff[out_used] = '\0'; return (out_buff); }
// Algoritme 'Shunting Yard' pour faire la conversion du type Infixée pour le RPN char *shuntingYard(char *stringRPN){ #define spush(x) conversionStack[l_stack++].valeur = x #define spop() conversionStack[--l_stack].valeur char *valeurIndiv = (char*) strtok(stringRPN, " "); char *postFixe = malloc(100 * sizeof(char)); opAssoc conversionStack[100]; int l_stack = 0; int flag = 0; strcpy(postFixe, ""); while(valeurIndiv != NULL) { // Si le caractère est constante mettre dans la pile if((ILESTNOMBRE) || (ILESTVARIABLE)) { strcat(postFixe, valeurIndiv); strcat(postFixe, " "); // Si non, on doit verifier sa priorité et associativité } else { if (PRIORITEDEUX) { conversionStack[l_stack].priorite = 2; conversionStack[l_stack].associativite = 1; } else if (PRIORITETROIS) { conversionStack[l_stack].priorite = 3; conversionStack[l_stack].associativite = 1; } else { conversionStack[l_stack].priorite = 0; conversionStack[l_stack].associativite = 0; } // Verification s'il y a la presence d'un () if (valeurIndiv[0] == '(') flag = l_stack; // Verification de la priorite de l'algoritme if (l_stack && conversionStack[l_stack-1].priorite == conversionStack[l_stack].priorite) { strcat(postFixe, spop()); strcat(postFixe, " "); conversionStack[l_stack].priorite = conversionStack[l_stack+1].priorite; } spush(valeurIndiv); } if(valeurIndiv[0] == ')') { l_stack--; while(l_stack != flag+1) { strcat(postFixe, spop()); strcat(postFixe, " "); } l_stack--; } valeurIndiv = (char*) strtok(NULL, " "); } // Si il a déjà fini fait le pop jusqu'à le fin while(l_stack) { strcat(postFixe, spop()); strcat(postFixe, " "); } free(valeurIndiv); return postFixe; }
static _cstackitem * _push_frame(_pit *cp) { return spush(current_ctx->cs, cp); }
void generar_multiplicacion(Element *obj) { Element *operando1 = (Element *)malloc(sizeof(Element)); Element *operando2 = (Element *)malloc(sizeof(Element)); spop(&pila, (void *)&operando2); spop(&pila, (void *)&operando1); if (operando1->code == REGISTRO && operando1->value == 0) { //operando1 ya esta en AL, pasar operando2 a un registro distinto de AH, si es necesario ; } else { if (operando2->code == REGISTRO && operando2->value == 0) { //operando2 esta en AL, swapear las variables y pasar a operando2 a un registro distinto de AH, si es necesario Element *aux = operando1; operando1 = operando2; operando2 = aux; } else { //ninguno esta en AL. Pasar operando1 a AL y operando2 a un registro distinto de AH, si es necesario Element *op_aux = get_free_AL(); if (operando1->code == REGISTRO) { fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando1->name); state[operando1->value] = 0; operando1 = op_aux; } else { if (operando1->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando1->name); operando1 = op_aux; } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando1->value); operando1 = op_aux; } } state[0] = 1; } } if (operando2->code == REGISTRO) { if (operando2->value == 1) { //esta en AH, moverlo a otro registro libre. Element *op_aux = get_free_notA(); fprintf(output_fd, "\t\tMOV\t%s, %s\n", op_aux->name, operando2->name); operando2 = op_aux; state[operando2->value] = 1; } else { //esta en otro registro. No hacer nada. ; } } else { //conseguir un registro libre distinto de AH y mover operando2 alli. Element *op_aux = get_free_notA(); if (operando2->code == IDENTIFICADOR) { fprintf(output_fd, "\t\tMOV\t%s, _%s\n", op_aux->name, operando2->name); operando2 = op_aux; } else { fprintf(output_fd, "\t\tMOV\t%s, %d\n", op_aux->name, operando2->value); operando2 = op_aux; } state[operando2->value] = 1; } state[1] = 0; //A esta altura, operando1 es AL y operando2 es otro registro distinto de AH fprintf(output_fd, "\t\tIMUL\t%s\n", operando2->name); incluir_chequeo_overflow(operando1); state[operando2->value] = 0; /*Libero el registro*/ //Apilo AL, la parte baja del resultado spush(&pila, (void *)operando1); }
static char *receive_chunked_http(const int request_fd) { char *raw_buf = NULL; size_t buf_size = 0; int times_read = 0; fd_set chan_fds; FD_ZERO(&chan_fds); FD_SET(request_fd, &chan_fds); const int maxfd = request_fd; while (1) { times_read++; /* Wait for data to be read. */ struct timeval tv = { .tv_sec = SELECT_TIMEOUT, .tv_usec = 0 }; select(maxfd + 1, &chan_fds, NULL, NULL, &tv); int count; /* How many bytes should we read: */ ioctl(request_fd, FIONREAD, &count); if (count <= 0) break; int old_offset = buf_size; buf_size += count; if (raw_buf != NULL) { char *new_buf = realloc(raw_buf, buf_size); if (new_buf != NULL) { raw_buf = new_buf; } else { goto error; } } else { raw_buf = calloc(1, buf_size); } int recvd = recv(request_fd, raw_buf + old_offset, count, 0); if (recvd != count) { log_msg(LOG_WARN, "Could not receive entire message."); } } /* printf("Full message is %s\n.", raw_buf); */ /* Check for a 200: */ if (raw_buf == NULL || strstr(raw_buf, "200") == NULL) { log_msg(LOG_ERR, "Could not find 200 return code in response."); goto error; } /* 4Chan throws us data as chunk-encoded HTTP. Rad. */ char *header_end = strstr(raw_buf, "\r\n\r\n"); char *cursor_pos = header_end + (sizeof(char) * 4); size_t json_total = 0; char *json_buf = NULL; while (1) { /* This is where the data begins. */ char *chunk_size_start = cursor_pos; char *chunk_size_end = strstr(chunk_size_start, "\r\n"); const int chunk_size_end_oft = chunk_size_end - chunk_size_start; /* We cheat a little and set the first \r to a \0 so strtol will * do the right thing. */ chunk_size_start[chunk_size_end_oft] = '\0'; const int chunk_size = strtol(chunk_size_start, NULL, 16); /* printf("Chunk size is %i. Thing is: %s.\n", chunk_size, chunk_size_start); */ /* The chunk string, the \r\n after it, the chunk itself and then another \r\n: */ cursor_pos += chunk_size + chunk_size_end_oft + 4; /* Copy the json into a pure buffer: */ int old_offset = json_total; json_total += chunk_size; if (json_total >= old_offset) { if (json_buf != NULL) { char *new_buf = realloc(json_buf, json_total); if (new_buf != NULL) { json_buf = new_buf; } else { goto error; } } else { json_buf = calloc(1, json_total); } } /* Copy it from after the <chunk_size>\r\n to the end of the chunk. */ memcpy(json_buf + old_offset, chunk_size_end + 2, chunk_size); /* Stop reading if we am play gods: */ if ((cursor_pos - raw_buf) > buf_size || chunk_size <= 0) break; } /* printf("The total json size is %zu.\n", json_total); */ /* printf("JSON:\n%s", json_buf); */ free(raw_buf); return json_buf; error: if (raw_buf != NULL) free(raw_buf); return NULL; } static int connect_to_host(const char *host) { struct addrinfo hints = {0}; struct addrinfo *res = NULL; int request_fd; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; getaddrinfo(host, "80", &hints, &res); request_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (request_fd < 0) { log_msg(LOG_ERR, "Could not create socket."); goto error; } int opt = 1; setsockopt(request_fd, SOL_SOCKET, SO_REUSEADDR, (void*) &opt, sizeof(opt)); int rc = connect(request_fd, res->ai_addr, res->ai_addrlen); if (rc == -1) { log_msg(LOG_ERR, "Could not connect to host %s.", host); goto error; } freeaddrinfo(res); return request_fd; error: freeaddrinfo(res); close(request_fd); return -1; } static char *receive_http(const int request_fd, size_t *out) { char *raw_buf = NULL; size_t buf_size = 0; int times_read = 0; fd_set chan_fds; FD_ZERO(&chan_fds); FD_SET(request_fd, &chan_fds); const int maxfd = request_fd; while (1) { times_read++; /* Wait for data to be read. */ struct timeval tv = { .tv_sec = SELECT_TIMEOUT, .tv_usec = 0 }; select(maxfd + 1, &chan_fds, NULL, NULL, &tv); int count; /* How many bytes should we read: */ ioctl(request_fd, FIONREAD, &count); if (count <= 0) break; int old_offset = buf_size; buf_size += count; if (raw_buf != NULL) { char *new_buf = realloc(raw_buf, buf_size); if (new_buf != NULL) { raw_buf = new_buf; } else { goto error; } } else { raw_buf = calloc(1, buf_size); } /* printf("IOCTL: %i.\n", count); */ recv(request_fd, raw_buf + old_offset, count, 0); } /* printf("Full message is %s\n.", raw_buf); */ /* Check for a 200: */ if (raw_buf == NULL || strstr(raw_buf, "200") == NULL) { log_msg(LOG_ERR, "Could not find 200 return code in response."); goto error; } /* 4Chan throws us data as chunk-encoded HTTP. Rad. */ char *header_end = strstr(raw_buf, "\r\n\r\n"); char *cursor_pos = header_end + (sizeof(char) * 4); size_t result_size = 0; char *offset_for_clength = strnstr(raw_buf, "Content-Length: ", buf_size); if (offset_for_clength == NULL) { log_msg(LOG_ERR, "Could not find content-length."); goto error; } char siz_buf[128] = {0}; int i = 0; const char *to_read = offset_for_clength + strlen("Content-Length: "); while (to_read[i] != '\r' && to_read[i + 1] != '\n' && i < sizeof(siz_buf)) { siz_buf[i] = to_read[i]; i++; } result_size = strtol(siz_buf, NULL, 10); log_msg(LOG_INFO, "Received %lu bytes.", result_size); char *to_return = malloc(result_size); memcpy(to_return, cursor_pos, result_size); *out = result_size; free(raw_buf); return to_return; error: if (raw_buf != NULL) free(raw_buf); return NULL; } static void ensure_directory_for_board(const char *board) { /* Long enough for WEBMS_DIR, a /, the board and a NULL terminator */ const size_t buf_siz = strlen(webm_location()) + sizeof(char) * 2 + strnlen(board, MAX_BOARD_NAME_SIZE); char to_create[buf_siz]; memset(to_create, '\0', buf_siz); /* ./webms/b */ snprintf(to_create, buf_siz, "%s/%s", webm_location(), board); struct stat st = {0}; if (stat(to_create, &st) == -1) { log_msg(LOG_WARN, "Creating directory %s.", to_create); mkdir(to_create, 0755); } } static ol_stack *build_thread_index() { int request_fd = 0; request_fd = connect_to_host(FOURCHAN_API_HOST); if (request_fd < 0) { log_msg(LOG_ERR, "Could not connect to %s.", FOURCHAN_API_HOST); goto error; } log_msg(LOG_INFO, "Connected to %s.", FOURCHAN_API_HOST); /* This is where we'll queue up images to be downloaded. */ ol_stack *images_to_download = NULL; images_to_download = malloc(sizeof(ol_stack)); images_to_download->next = NULL; images_to_download->data = NULL; int i; for (i = 0; i < (sizeof(BOARDS)/sizeof(BOARDS[0])); i++) { const char *current_board = BOARDS[i]; const size_t api_request_siz = strlen(CATALOG_REQUEST) + strnlen(current_board, MAX_BOARD_NAME_SIZE); char new_api_request[api_request_siz]; memset(new_api_request, '\0', api_request_siz); snprintf(new_api_request, api_request_siz, CATALOG_REQUEST, current_board); int rc = send(request_fd, new_api_request, strlen(new_api_request), 0); if (strlen(new_api_request) != rc) goto error; log_msg(LOG_INFO, "Sent request to %s.", FOURCHAN_API_HOST); char *all_json = receive_chunked_http(request_fd); if (all_json == NULL) { log_msg(LOG_WARN, "Could not receive chunked HTTP from board for /%s/.", current_board); continue; } ol_stack *matches = parse_catalog_json(all_json, current_board); while (matches->next != NULL) { /* Pop our thread_match off the stack */ thread_match *match = (thread_match*) spop(&matches); ensure_directory_for_board(match->board); log_msg(LOG_INFO, "/%s/ - Requesting thread %i...", current_board, match->thread_num); /* Template out a request to the 4chan API for it */ /* (The 30 is because I don't want to find the length of the * integer thread number) */ const size_t thread_req_size = sizeof(THREAD_REQUEST) + strnlen(match->board, MAX_BOARD_NAME_SIZE) + 30; char templated_req[thread_req_size]; memset(templated_req, '\0', thread_req_size); snprintf(templated_req, thread_req_size, THREAD_REQUEST, match->board, match->thread_num); /* Send that shit over the wire */ rc = send(request_fd, templated_req, strlen(templated_req), 0); if (rc != strlen(templated_req)) { log_msg(LOG_ERR, "Could not send all of request."); continue; } char *thread_json = receive_chunked_http(request_fd); if (thread_json == NULL) { log_msg(LOG_WARN, "Could not receive chunked HTTP for thread. continuing."); /* Reopen and manipulate the socket. */ close(request_fd); request_fd = connect_to_host(FOURCHAN_API_HOST); free(match); continue; } ol_stack *thread_matches = parse_thread_json(thread_json, match); while (thread_matches->next != NULL) { post_match *p_match = (post_match *)spop(&thread_matches); /* TODO: Don't add it to the images to download if we already * have that image, with that size, from that board. */ char fname[MAX_IMAGE_FILENAME_SIZE] = {0}; get_image_filename(fname, p_match); struct stat ifname = {0}; if (stat(fname, &ifname) != -1 && ifname.st_size == p_match->size) { log_msg(LOG_INFO, "Skipping %s.", fname); free(p_match); continue; } spush(&images_to_download, p_match); } free(thread_matches); free(thread_json); free(match); } free(matches); free(all_json); } /* We don't need the API socket anymore. */ close(request_fd); return images_to_download; error: if (images_to_download != NULL) { while (images_to_download->next != NULL) { post_match *_match = (post_match *)spop(&images_to_download); free(_match); } free(images_to_download); } close(request_fd); return NULL; }