void mm_look(MazeMap *mm, const char *line, RelDir rel_dir) { Dir front = TURN(mm->dir, rel_dir), left = TURN(front, LEFT), right = TURN(front, RIGHT), back = TURN(front, BACK); int r = mm->loc.r, c = mm->loc.c; while (*line) { bool open_left = false, open_right = false; switch (*line++) { case 'B': /* opening on both sides */ open_left = open_right = true; break; case 'L': /* opening on left side */ open_left = true; break; case 'R': /* opening on right side */ open_right = true; break; case 'N': /* no opening on either side */ break; case 'W': /* wall immediately ahead: */ SET_WALL(mm, r, c, front, PRESENT); assert(*line == '\0'); return; default: /* invalid char */ assert(0); } push_border(mm, r, c, front); r = RDR(r, front); c = CDC(c, front); SET_SQUARE(mm, r, c, PRESENT); SET_WALL(mm, r, c, back, ABSENT); SET_WALL(mm, r, c, left, open_left ? ABSENT : PRESENT); SET_WALL(mm, r, c, right, open_right ? ABSENT : PRESENT); if (open_left) { SET_SQUARE(mm, RDR(r, left), CDC(c, left), PRESENT); push_border(mm, r, c, left); } if (open_right) { SET_SQUARE(mm, RDR(r, right), CDC(c, right), PRESENT); push_border(mm, r, c, right); } } assert(0); /* shouldn't get here: every line must end with W */ return; }
static void key_clbk(enum wm_key key, enum wm_state state, void* data) { assert(data); if(state == WM_PRESS) { struct rdr_term* term = data; if(key == WM_KEY_ESC) { g_exit = 1; } else if(key == WM_KEY_ENTER) { RDR(term_write_return(term)); } else if(key == WM_KEY_BACKSPACE) { RDR(term_write_backspace(term)); } else if(key == WM_KEY_TAB) { RDR(term_write_tab(term)); } else if(key == WM_KEY_DEL) { RDR(term_write_suppr(term)); } else if(key == WM_KEY_RIGHT) { RDR(term_translate_cursor(term, 1)); } else if(key == WM_KEY_LEFT) { RDR(term_translate_cursor(term, -1)); } else if(key == WM_KEY_END) { RDR(term_translate_cursor(term, INT_MAX)); } else if(key == WM_KEY_HOME) { RDR(term_translate_cursor(term, -INT_MAX)); } } }
static Point explore(MazeMap *mm) { Point res; int r, c, dir; int best_v = 0, best_dist = 0; for (r = 0; r < HEIGHT; ++r) { for (c = 0; c < WIDTH; ++c) { if (dist[r][c] != -1) { int v = 0; for (dir = 0; dir < 4; ++dir) { if (SQUARE(mm, RDR(r, dir), CDC(c, dir)) == UNKNOWN && WALL(mm, r, c, dir) != PRESENT) ++v; } if (v > best_v || (v == best_v && dist[r][c] < best_dist)) { best_v = v; best_dist = dist[r][c]; res.r = r; res.c = c; } } } } assert(best_v > 0); return res; }
static void term_char_clbk(wchar_t wch, enum wm_state state, void* data) { struct app* app = data; enum app_error app_err = APP_NO_ERROR; const char ch = (char)wch; assert(data); if(state != WM_PRESS || wch > 126 || wch < 32) goto exit; app_err = app_command_buffer_write_char(app->term.cmdbuf, ch); if(APP_NO_ERROR != app_err) { APP_PRINT_ERR (app->logger, "command buffer input error: `%s'\n", app_error_string(app_err)); goto error; } RDR(term_print_wchar (app->term.render_term, RDR_TERM_CMDOUT, wch, RDR_TERM_COLOR_WHITE)); exit: return; error: goto exit; }
static bool mark_dead_end(MazeMap *mm, bool dead_end[HEIGHT][WIDTH], int r, int c) { int num_walls = 0, num_dead_adjacent = 0, dir; bool changed = false; if (dead_end[r][c]) return false; for (dir = 0; dir < 4; ++dir) { int w = WALL(mm, r, c, dir); if (w == PRESENT) ++num_walls; else if (w == ABSENT && dead_end[RDR(r, dir)][CDC(c, dir)]) ++num_dead_adjacent; } assert(num_walls + num_dead_adjacent < 4); if (num_walls + num_dead_adjacent == 3) { dead_end[r][c] = true; if (SQUARE(mm, r, c) == UNKNOWN) { SET_SQUARE(mm, r, c, PRESENT); changed = true; } for (dir = 0; dir < 4; ++dir) { if (WALL(mm, r, c, dir) == UNKNOWN) { SET_WALL(mm, r, c, dir, ABSENT); changed = true; } } for (dir = 0; dir < 4; ++dir) { if (WALL(mm, r, c, dir) == ABSENT) { if (mark_dead_end(mm, dead_end, RDR(r, dir), CDC(c, dir))) changed = true; } } } return changed; }
static void char_clbk(wchar_t ch, enum wm_state state, void* data) { assert(data); if(state == WM_PRESS) { struct rdr_term* term = data; if(ch >= FIRST_CHAR && ch <= LAST_CHAR) RDR(term_print_wchar(term, RDR_TERM_CMDOUT, ch, RDR_TERM_COLOR_WHITE)); } }
void mm_move(MazeMap *mm, char move) { RelDir rel_dir; switch (move) { case 'F': rel_dir = FRONT; break; case 'T': rel_dir = BACK; break; case 'L': rel_dir = LEFT; break; case 'R': rel_dir = RIGHT; break; default: assert(0); /* invalid char */ } mm->dir = TURN(mm->dir, rel_dir); push_border(mm, mm->loc.r, mm->loc.c, mm->dir); mm->loc.r = RDR(mm->loc.r, mm->dir); mm->loc.c = CDC(mm->loc.c, mm->dir); SET_SQUARE(mm, mm->loc.r, mm->loc.c, PRESENT); }
enum app_error app_shutdown_term(struct app* app) { enum app_error app_err = APP_NO_ERROR; if(!app) { app_err = APP_INVALID_ARGUMENT; goto error; } if(app->term.cmdbuf) APP(regular_command_buffer_ref_put(app->term.cmdbuf)); if(app->term.render_term) RDR(term_ref_put(app->term.render_term)); if(true == app->term.is_enabled) APP(enable_term(app, false)); memset(&app->term, 0, sizeof(app->term)); exit: return app_err; error: goto exit; }
/******************************************************************************* * * Helper functions. * ******************************************************************************/ static void command_completion(struct term* term) { struct app* app = NULL; const char* cmdbuf = NULL; const char** list = NULL; size_t cursor = 0; size_t len = 0; assert(term); app = CONTAINER_OF(term, struct app, term); APP(command_buffer_completion(app->term.cmdbuf, &len, &list)); APP(get_command_buffer_string(app->term.cmdbuf, &cursor, &cmdbuf)); RDR(clear_term(app->term.render_term, RDR_TERM_CMDOUT)); RDR(term_print_string (app->term.render_term, RDR_TERM_CMDOUT, cmdbuf, RDR_TERM_COLOR_WHITE)); RDR(term_translate_cursor(app->term.render_term, INT_MIN)); RDR(term_translate_cursor(app->term.render_term, cursor)); if(0 != len) { if(1 < len) { size_t i = 0; for(i = 0; i < len; ++i) { if(0 != i) { RDR(term_print_wchar (app->term.render_term, RDR_TERM_STDOUT, L'\t', RDR_TERM_COLOR_WHITE)); } RDR(term_print_string (app->term.render_term, RDR_TERM_STDOUT, list[i], RDR_TERM_COLOR_WHITE)); } RDR(term_print_wchar (app->term.render_term, RDR_TERM_STDOUT, L'\n', RDR_TERM_COLOR_WHITE)); } } }
void icmp6_print(const u_char *bp, u_int length, const u_char *bp2) { register const struct icmp6_hdr *dp; register const struct ip6_hdr *ip; register const char *str; register const struct ip6_hdr *oip; register const struct udphdr *ouh; register int hlen, dport; register const u_char *ep; char buf[256]; int icmp6len; #if 0 #define TCHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) goto trunc #endif dp = (struct icmp6_hdr *)bp; ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); str = buf; /* 'ep' points to the end of avaible data. */ ep = snapend; if (ip->ip6_plen) icmp6len = (ntohs(ip->ip6_plen) + sizeof(struct ip6_hdr) - (bp - bp2)); else /* XXX: jumbo payload case... */ icmp6len = snapend - bp; #if 0 (void)printf("%s > %s: ", ip6addr_string(&ip->ip6_src), ip6addr_string(&ip->ip6_dst)); #endif TCHECK(dp->icmp6_code); switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_DST_UNREACH_NOROUTE: printf("icmp6: %s unreachable route", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_ADMIN: printf("icmp6: %s unreachable prohibited", ip6addr_string(&oip->ip6_dst)); break; #ifdef ICMP6_DST_UNREACH_BEYONDSCOPE case ICMP6_DST_UNREACH_BEYONDSCOPE: #else case ICMP6_DST_UNREACH_NOTNEIGHBOR: #endif printf("icmp6: %s beyond scope of source address %s", ip6addr_string(&oip->ip6_dst), ip6addr_string(&oip->ip6_src)); break; case ICMP6_DST_UNREACH_ADDR: printf("icmp6: %s unreachable address", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_DST_UNREACH_NOPORT: TCHECK(oip->ip6_nxt); hlen = sizeof(struct ip6_hdr); ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = ntohs(ouh->uh_dport); switch (oip->ip6_nxt) { case IPPROTO_TCP: printf("icmp6: %s tcp port %s unreachable", ip6addr_string(&oip->ip6_dst), tcpport_string(dport)); break; case IPPROTO_UDP: printf("icmp6: %s udp port %s unreachable", ip6addr_string(&oip->ip6_dst), udpport_string(dport)); break; default: printf("icmp6: %s protocol %d port %d unreachable", ip6addr_string(&oip->ip6_dst), oip->ip6_nxt, dport); break; } break; default: printf("icmp6: %s unreachable code-#%d", ip6addr_string(&oip->ip6_dst), dp->icmp6_code); break; } break; case ICMP6_PACKET_TOO_BIG: TCHECK(dp->icmp6_mtu); printf("icmp6: too big %u", (u_int32_t)ntohl(dp->icmp6_mtu)); break; case ICMP6_TIME_EXCEEDED: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_TIME_EXCEED_TRANSIT: printf("icmp6: time exceeded in-transit for %s", ip6addr_string(&oip->ip6_dst)); break; case ICMP6_TIME_EXCEED_REASSEMBLY: printf("icmp6: ip6 reassembly time exceeded"); break; default: printf("icmp6: time exceeded code-#%d", dp->icmp6_code); break; } break; case ICMP6_PARAM_PROB: TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_PARAMPROB_HEADER: printf("icmp6: parameter problem errorneous - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_NEXTHEADER: printf("icmp6: parameter problem next header - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; case ICMP6_PARAMPROB_OPTION: printf("icmp6: parameter problem option - octet %u", (u_int32_t)ntohl(dp->icmp6_pptr)); break; default: printf("icmp6: parameter problem code-#%d", dp->icmp6_code); break; } break; case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: printf("icmp6: echo %s", dp->icmp6_type == ICMP6_ECHO_REQUEST ? "request" : "reply"); if (vflag) { TCHECK(dp->icmp6_seq); printf(" (id:%04x seq:%u)", ntohs(dp->icmp6_id), ntohs(dp->icmp6_seq)); } break; case ICMP6_MEMBERSHIP_QUERY: printf("icmp6: multicast listener query "); if (length == MLD_V1_QUERY_MINLEN) { mld6_print((const u_char *)dp); } else if (length >= MLD_V2_QUERY_MINLEN) { printf("v2 "); mldv2_query_print((const u_char *)dp, length); } else { printf("unknown-version (len %u) ", length); } break; case ICMP6_MEMBERSHIP_REPORT: printf("icmp6: multicast listener report "); mld6_print((const u_char *)dp); break; case ICMP6_MEMBERSHIP_REDUCTION: printf("icmp6: multicast listener done "); mld6_print((const u_char *)dp); break; case ND_ROUTER_SOLICIT: printf("icmp6: router solicitation "); if (vflag) { #define RTSOLLEN 8 icmp6_opt_print((const u_char *)dp + RTSOLLEN, icmp6len - RTSOLLEN); } break; case ND_ROUTER_ADVERT: printf("icmp6: router advertisement"); if (vflag) { struct nd_router_advert *p; p = (struct nd_router_advert *)dp; TCHECK(p->nd_ra_retransmit); printf("(chlim=%d, ", (int)p->nd_ra_curhoplimit); if (p->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) printf("M"); if (p->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) printf("O"); if (p->nd_ra_flags_reserved != 0) printf(" "); printf("router_ltime=%d, ", ntohs(p->nd_ra_router_lifetime)); printf("reachable_time=%u, ", (u_int32_t)ntohl(p->nd_ra_reachable)); printf("retrans_time=%u)", (u_int32_t)ntohl(p->nd_ra_retransmit)); #define RTADVLEN 16 icmp6_opt_print((const u_char *)dp + RTADVLEN, icmp6len - RTADVLEN); } break; case ND_NEIGHBOR_SOLICIT: { struct nd_neighbor_solicit *p; p = (struct nd_neighbor_solicit *)dp; TCHECK(p->nd_ns_target); printf("icmp6: neighbor sol: who has %s", ip6addr_string(&p->nd_ns_target)); if (vflag) { #define NDSOLLEN 24 icmp6_opt_print((const u_char *)dp + NDSOLLEN, icmp6len - NDSOLLEN); } } break; case ND_NEIGHBOR_ADVERT: { struct nd_neighbor_advert *p; p = (struct nd_neighbor_advert *)dp; TCHECK(p->nd_na_target); printf("icmp6: neighbor adv: tgt is %s", ip6addr_string(&p->nd_na_target)); if (vflag) { #define ND_NA_FLAG_ALL \ (ND_NA_FLAG_ROUTER|ND_NA_FLAG_SOLICITED|ND_NA_FLAG_OVERRIDE) /* we don't need ntohl() here. see advanced-api-04. */ if (p->nd_na_flags_reserved & ND_NA_FLAG_ALL) { #undef ND_NA_FLAG_ALL u_int32_t flags; flags = p->nd_na_flags_reserved; printf("("); if (flags & ND_NA_FLAG_ROUTER) printf("R"); if (flags & ND_NA_FLAG_SOLICITED) printf("S"); if (flags & ND_NA_FLAG_OVERRIDE) printf("O"); printf(")"); } #define NDADVLEN 24 icmp6_opt_print((const u_char *)dp + NDADVLEN, icmp6len - NDADVLEN); } } break; case ND_REDIRECT: { #define RDR(i) ((struct nd_redirect *)(i)) char tgtbuf[INET6_ADDRSTRLEN], dstbuf[INET6_ADDRSTRLEN]; TCHECK(RDR(dp)->nd_rd_dst); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_target, tgtbuf, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &RDR(dp)->nd_rd_dst, dstbuf, INET6_ADDRSTRLEN); printf("icmp6: redirect %s to %s", dstbuf, tgtbuf); #define REDIRECTLEN 40 if (vflag) { icmp6_opt_print((const u_char *)dp + REDIRECTLEN, icmp6len - REDIRECTLEN); } break; } case ICMP6_ROUTER_RENUMBERING: switch (dp->icmp6_code) { case ICMP6_ROUTER_RENUMBERING_COMMAND: printf("icmp6: router renum command"); break; case ICMP6_ROUTER_RENUMBERING_RESULT: printf("icmp6: router renum result"); break; default: printf("icmp6: router renum code-#%d", dp->icmp6_code); break; } break; #ifdef ICMP6_WRUREQUEST case ICMP6_WRUREQUEST: /*ICMP6_FQDN_QUERY*/ { int siz; siz = ep - (u_char *)(dp + 1); if (siz == 4) printf("icmp6: who-are-you request"); else { printf("icmp6: FQDN request"); if (vflag) { if (siz < 8) printf("?(icmp6_data %d bytes)", siz); else if (8 < siz) printf("?(extra %d bytes)", siz - 8); } } break; } #endif /*ICMP6_WRUREQUEST*/ #ifdef ICMP6_WRUREPLY case ICMP6_WRUREPLY: /*ICMP6_FQDN_REPLY*/ { enum { UNKNOWN, WRU, FQDN } mode = UNKNOWN; u_char const *buf; u_char const *cp = NULL; buf = (u_char *)(dp + 1); /* fair guess */ if (buf[12] == ep - buf - 13) mode = FQDN; else if (dp->icmp6_code == 1) mode = FQDN; /* wild guess */ if (mode == UNKNOWN) { cp = buf + 4; while (cp < ep) { if (!isprint(*cp++)) mode = FQDN; } } #ifndef abs #define abs(a) ((0 < (a)) ? (a) : -(a)) #endif if (mode == UNKNOWN && 2 < abs(buf[12] - (ep - buf - 13))) mode = WRU; if (mode == UNKNOWN) mode = FQDN; if (mode == WRU) { cp = buf + 4; printf("icmp6: who-are-you reply(\""); } else if (mode == FQDN) { cp = buf + 13; printf("icmp6: FQDN reply(\""); } for (; cp < ep; cp++) printf((isprint(*cp) ? "%c" : "\\%03o"), *cp); printf("\""); if (vflag) { printf(",%s", mode == FQDN ? "FQDN" : "WRU"); if (mode == FQDN) { int ttl; ttl = (int)ntohl(*(u_int32_t *)&buf[8]); if (dp->icmp6_code == 1) printf(",TTL=unknown"); else if (ttl < 0) printf(",TTL=%d:invalid", ttl); else printf(",TTL=%d", ttl); if (buf[12] != ep - buf - 13) { (void)printf(",invalid namelen:%d/%u", buf[12], (unsigned int)(ep - buf - 13)); } } } printf(")"); break; } #endif /*ICMP6_WRUREPLY*/ case MLDV2_LISTENER_REPORT: printf("multicast listener report v2"); mldv2_report_print((const u_char *) dp, length); break; default: printf("icmp6: type-#%d", dp->icmp6_type); break; } if (vflag) { u_int16_t sum; if (TTEST2(dp->icmp6_type, length)) { sum = icmp6_cksum(ip, dp, length); if (sum != 0) printf(" [bad icmp6 cksum %x!]", sum); else printf(" [icmp6 cksum ok]"); } } return; trunc: fputs("[|icmp6]", stdout); #if 0 #undef TCHECK #endif }
static void term_key_clbk(enum wm_key key, enum wm_state state, void* data) { const char* cstr = NULL; struct term* term = NULL; enum app_error app_err = APP_NO_ERROR; size_t cursor = 0; assert(data); if(state != WM_PRESS) return; term = &((struct app*)data)->term; switch(key) { case WM_KEY_ENTER: RDR(term_write_return(term->render_term)); app_err = app_execute_command_buffer(term->cmdbuf); assert(APP_COMMAND_ERROR == app_err || APP_NO_ERROR == app_err); break; case WM_KEY_BACKSPACE: RDR(term_write_backspace(term->render_term)); APP(command_buffer_write_backspace(term->cmdbuf)); break; case WM_KEY_DEL: RDR(term_write_suppr(term->render_term)); APP(command_buffer_write_suppr(term->cmdbuf)); break; case WM_KEY_RIGHT: RDR(term_translate_cursor(term->render_term, 1)); APP(command_buffer_move_cursor(term->cmdbuf, 1)); break; case WM_KEY_LEFT: RDR(term_translate_cursor(term->render_term, -1)); APP(command_buffer_move_cursor(term->cmdbuf, -1)); break; case WM_KEY_END: RDR(term_translate_cursor(term->render_term, INT_MAX)); APP(command_buffer_move_cursor(term->cmdbuf, INT_MAX)); break; case WM_KEY_HOME: RDR(term_translate_cursor(term->render_term, INT_MIN)); APP(command_buffer_move_cursor(term->cmdbuf, INT_MIN)); break; case WM_KEY_UP: case WM_KEY_DOWN: if(WM_KEY_UP == key ) { APP(command_buffer_history_next(term->cmdbuf)); } else { APP(command_buffer_history_prev(term->cmdbuf)); } APP(get_command_buffer_string(term->cmdbuf, &cursor, &cstr)); RDR(clear_term(term->render_term, RDR_TERM_CMDOUT)); RDR(term_print_string (term->render_term, RDR_TERM_CMDOUT, cstr, RDR_TERM_COLOR_WHITE)); RDR(term_translate_cursor(term->render_term, INT_MIN)); RDR(term_translate_cursor(term->render_term, cursor)); break; case WM_KEY_TAB: command_completion(term); break; default: break; } }
int main(int argc, char** argv) { /* Window manager data structures. */ struct wm_device* dev = NULL; struct wm_window* win = NULL; const struct wm_window_desc win_desc = { 800, 600, 0 }; /* Renderer data structure. */ struct rdr_glyph_desc glyph_desc_list[NB_CHARS]; struct rdr_font* font = NULL; struct rdr_frame* frame = NULL; struct rdr_system* sys = NULL; struct rdr_term* term = NULL; /* Resources data structure. */ struct rsrc_context* ctxt = NULL; struct rsrc_font* rfont = NULL; /* Miscellaneous data. */ const char* driver_name = NULL; const char* font_name = NULL; size_t line_space = 0; size_t i = 0; bool b = false; if(argc != 3) { printf("usage: %s RB_DRIVER FONT\n", argv[0]); return -1; } driver_name = argv[1]; font_name = argv[2]; /* Setup the render font. */ RSRC(create_context(NULL, &ctxt)); RSRC(create_font(ctxt, font_name, &rfont)); if(RSRC(is_font_scalable(rfont, &b)), b) RSRC(font_size(rfont, 18, 18)); for(i = 0; i < NB_CHARS; ++i) { struct rsrc_glyph* glyph = NULL; struct rsrc_glyph_desc glyph_desc; size_t width = 0; size_t height = 0; size_t Bpp = 0; size_t size = 0; RSRC(font_glyph(rfont, (wchar_t)(i + FIRST_CHAR), &glyph)); /* Get glyph desc. */ RSRC(glyph_desc(glyph, &glyph_desc)); glyph_desc_list[i].width = glyph_desc.width; glyph_desc_list[i].character = glyph_desc.character; glyph_desc_list[i].bitmap_left = glyph_desc.bbox.x_min; glyph_desc_list[i].bitmap_top = glyph_desc.bbox.y_min; /* Get glyph bitmap. */ RSRC(glyph_bitmap(glyph, true, &width, &height, &Bpp, NULL)); glyph_desc_list[i].bitmap.width = width; glyph_desc_list[i].bitmap.height = height; glyph_desc_list[i].bitmap.bytes_per_pixel = Bpp; glyph_desc_list[i].bitmap.buffer = NULL; size = width * height * Bpp; if(0 != size) { unsigned char* buffer = MEM_CALLOC(&mem_default_allocator, 1, size); RSRC(glyph_bitmap(glyph, true, NULL, NULL, NULL, buffer)); glyph_desc_list[i].bitmap.buffer = buffer; } RSRC(glyph_ref_put(glyph)); } RSRC(font_line_space(rfont, &line_space)); RSRC(font_ref_put(rfont)); RSRC(context_ref_put(ctxt)); WM(create_device(NULL, &dev)); WM(create_window(dev, &win_desc, &win)); RDR(create_system(driver_name, NULL, &sys)); RDR(create_frame (sys, (struct rdr_frame_desc[]){{win_desc.width,win_desc.height}}, &frame));