static void destroy_symbol(void *ptr) { struct symbol *sym = (struct symbol *) ptr; if (! sym) return; switch (sym->type) { case UNKNOWN: break; case TERMINAL: destroy_terminal(&sym->t); break; case NONTERMINAL: case START_NONTERMINAL: destroy_nonterminal(&sym->nt); break; } if (sym->host_type) free((void *)sym->host_type); if (sym->destructor_code) free((void *)sym->destructor_code); free(sym); }
void destroy_all_terminals() { struct terminal *term; while ((void *)(term = terminals.next) != &terminals) destroy_terminal(term); }
void in_term(struct terminal *term) { struct event *ev; int r; unsigned char *iq; if ((unsigned)term->qlen + ALLOC_GR > MAXINT) overalloc(); iq = mem_realloc(term->input_queue, term->qlen + ALLOC_GR); term->input_queue = iq; if ((r = read(term->fdin, iq + term->qlen, ALLOC_GR)) <= 0) { if (r == -1 && errno != ECONNRESET) error("ERROR: error %d on terminal: could not read event", errno); destroy_terminal(term); return; } term->qlen += r; test_queue: if ((size_t)term->qlen < sizeof(struct event)) return; ev = (struct event *)iq; r = sizeof(struct event); if (ev->ev != EV_INIT && ev->ev != EV_RESIZE && ev->ev != EV_REDRAW && ev->ev != EV_KBD && ev->ev != EV_MOUSE && ev->ev != EV_ABORT) { error("ERROR: error on terminal: bad event %d", ev->ev); goto mm; } if (ev->ev == EV_INIT) { int init_len; if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int)) return; init_len = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); if ((size_t)term->qlen < sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len) return; memcpy(term->term, iq + sizeof(struct event), MAX_TERM_LEN); term->term[MAX_TERM_LEN - 1] = 0; memcpy(term->cwd, iq + sizeof(struct event) + MAX_TERM_LEN, MAX_CWD_LEN); term->cwd[MAX_CWD_LEN - 1] = 0; term->environment = *(int *)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN); ev->b = (long)(iq + sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + sizeof(int)); r = sizeof(struct event) + MAX_TERM_LEN + MAX_CWD_LEN + 2 * sizeof(int) + init_len; sync_term_specs(); } if (ev->ev == EV_REDRAW || ev->ev == EV_RESIZE || ev->ev == EV_INIT) { struct window *win; send_redraw: if (ev->x < 0 || ev->y < 0) { error("ERROR: bad terminal size: %d, %d", (int)ev->x, (int)ev->y); goto mm; } alloc_term_screen(term, ev->x, ev->y); clear_terminal(term); erase_screen(term); term->redrawing = 1; foreachback(win, term->windows) win->handler(win, ev, 0); term->redrawing = 0; } if (ev->ev == EV_KBD || ev->ev == EV_MOUSE) { if (ev->ev == EV_KBD && upcase(ev->x) == 'L' && ev->y == KBD_CTRL) { ev->ev = EV_REDRAW; ev->x = term->x; ev->y = term->y; goto send_redraw; } else if (ev->ev == EV_KBD && ev->x == KBD_CTRL_C) ((struct window *)term->windows.prev)->handler(term->windows.prev, ev, 0); else ((struct window *)term->windows.next)->handler(term->windows.next, ev, 0); } if (ev->ev == EV_ABORT) { destroy_terminal(term); return; } /*redraw_screen(term);*/ mm: if (term->qlen == r) term->qlen = 0; else memmove(iq, iq + r, term->qlen -= r); goto test_queue; }