static void flush_string(void) { if (sav_str_len<=0) return; add_string(0); outcmd('"', 0); if (sav_str_len<=0) return; { int outoff = 0, tapeoff = 0; int direction = 1; int flipcount = 1; struct mem* p = tapezero; for(;;) { if (p->is_set) break; if (direction > 0 && p->n) { p=p->n; tapeoff ++; } else if (direction < 0 && p->p) { p=p->p; tapeoff --; } else if (flipcount) { flipcount--; direction = -direction; } else { fprintf(stderr, "FAILED\n"); exit(1); } } if (tapeoff > outoff) { outcmd('>', tapeoff-outoff); outoff=tapeoff; } if (tapeoff < outoff) { outcmd('<', outoff-tapeoff); outoff=tapeoff; } tapezero = p; curroff -= tapeoff; } { char c=0, *p = sav_str_str; while(*p) { outcmd('=', (c = *p++)); outcmd('.', 0); } tapezero->cleaned = 1; tapezero->cleaned_val = c; sav_str_len = 0; } }
void flushtyping(int clearesc) { Text *t; ulong n; if(clearesc) typeesc = -1; if(typestart == typeend) { modified = 0; return; } t = which->user1; if(t != &cmd) modified = 1; rload(&t->rasp, typestart, typeend, &n); scratch[n] = 0; if(t==&cmd && typeend==t->rasp.nrunes && scratch[typeend-typestart-1]=='\n'){ setlock(); outcmd(); } outTslS(Ttype, t->tag, typestart, scratch); typestart = -1; typeend = -1; XFlush(_dpy); }
void menu2hit(void) { Text *t=(Text *)which->user1; int w = which-t->l; int m; m = menuhit(2, &mouse, t==&cmd? &menu2c : &menu2); if(lock || t->lock) return; switch(m){ case Cut: cut(t, w, true, true); break; case Paste: paste(t, w); break; case Snarf: snarf(t, w); break; case Exch: snarf(t, w); outT0(Tstartsnarf); setlock(); break; case Look: outTsll(Tlook, t->tag, which->p0, which->p1); setlock(); break; case Search: outcmd(); if(t==&cmd) outTsll(Tsend, 0 /*ignored*/, which->p0, which->p1); else outT0(Tsearch); setlock(); break; } }
void main(int argc, char *argv[]) { int i, got, scr; Text *t; Rectangle r; Flayer *nwhich; int fwdbut; if (argc >= 3 && strcmp(argv[1], "-r") == 0) { machine = argv[2]; } getscreen(argc, argv); fwdbut = scrollfwdbut(); iconinit(); initio(); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen.r; r.max.y = r.min.y+Dy(r)/5; flstart(screen.clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], stgettext, 1, &cmd); flinit(&cmd.l[0], r, font); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; for(;;got = waitforio()){ if(hasunlocked && RESHAPED()) reshape(); if(got&RHost) rcv(); if(got&RExtern){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RExtern); } if(got&RKeyboard) if(which) type(which, RKeyboard); else kbdblock(); if(got&RMouse){ if(lock==2 || !ptinrect(mouse.xy, screen.r)){ mouseunblock(); continue; } nwhich = flwhich(mouse.xy); scr = which && ptinrect(mouse.xy, which->scroll); if(mouse.buttons) flushtyping(1); if (chord == 1 && !mouse.buttons) chord = 0; if (chord) chord |= mouse.buttons; else if(mouse.buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) scroll(which, 1, fwdbut == 3 ? 1 : 3); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); if(mouse.buttons&1) chord = mouse.buttons; } } }else if((mouse.buttons&2) && which){ if(scr) scroll(which, 2, 2); else menu2hit(); }else if((mouse.buttons&4)){ if(scr) scroll(which, 3, fwdbut == 3 ? 3 : 1); else menu3hit(); }else if((mouse.buttons&8)){ scrollone(which, 1); }else if((mouse.buttons&16)){ scrollone(which, 3); } mouseunblock(); } if(chord) { t = (Text *)which->user1; if(!t->lock){ int w = which-t->l; if(chord&2){ cut(t, w, 1, 1); chord &= ~2; } if(chord&4){ paste(t, w); chord &= ~4; } } } } }
void outcmd(int ch, int count) { if (ch == '=') { count &= 255; } else { while (count>MAXPRLE) { outcmd(ch, MAXPRLE); count -= MAXPRLE; } if (count > 1) { switch(ch) { case '+': printf("u%d\n", count); break; case '-': printf("d%d\n", count); break; case '>': printf("r%d\n", count); break; case '<': printf("l%d\n", count); break; } return; } } switch(ch) { case '=': printf("f\nv=%d\ns\n", count); break; case '+': printf("u\n"); break; case '-': printf("d\n"); break; case '>': printf("r\n"); break; case '<': printf("l\n"); break; case '[': printf("f\n"); printf("while (! ~ $v 0){\n"); ind++; break; case ']': printf("f\n"); ind--; printf("}\n"); break; case '.': printf("o\n"); do_output = 1; break; case ',': printf("i\n"); do_input = 1; break; } switch(ch) { case '!': printf("#!/usr/bin/rc\n"); printf( "ptr=(1)\n" "\n" "fn f {\n" " p=t$^ptr\n" " v=$$p\n" " if (~ $v ()) v=0\n" "}\n" "\n" "fn s {\n" " $p=$v\n" "}\n" "\n" "fn r {\n" " carry=1\n" " nptr=()\n" " for(v in $ptr) {\n" " if (~ $carry 1) {\n" " carry=0\n" " if (~ $v 0) {\n" " v=1\n" " } else if (~ $v 9) {\n" " v=0\n" " carry=1\n" " } else {\n" " n=(2 3 4 5 6 7 8 9)\n" " v=$n($v)\n" " }\n" " }\n" " nptr=($nptr $v)\n" " }\n" " if (~ $carry 1) nptr=($nptr 1)\n" " ptr=$nptr\n" "}\n" "\n" "fn l {\n" " carry=1\n" " nptr=()\n" " pv=()\n" " for(v in $ptr) {\n" " nptr=($nptr $pv)\n" " if (~ $carry 1) {\n" " carry=0\n" " if (~ $v 0) {\n" " v=9\n" " carry=1\n" " } else {\n" " n=(0 1 2 3 4 5 6 7 8)\n" " v=$n($v)\n" " }\n" " }\n" " if (~ $v 0) {\n" " pv=$v\n" " } else {\n" " pv=()\n" " nptr=($nptr $v)\n" " }\n" " }\n" " ptr=$nptr\n" "}\n\n"); { int i; printf("inc=(\n"); for (i=0; i<256; i++) { printf(" %d", (i+2)&0xFF); if (i%16 == 15) printf("\n"); } printf(")\n\n"); printf("fn u {\n" " f\n"); printf(" if (~ $v 0) {\n"); printf(" v=1\n"); printf(" } else {\n"); printf(" v=$inc($v)\n"); printf(" }\n"); printf(" s\n" "}\n" "\n"); } { int i; printf("dec=(\n"); for (i=0; i<256; i++) { printf(" %d", (i)&0xFF); if (i%16 == 15) printf("\n"); } printf(")\n\n"); printf("fn d {\n" " f\n"); printf(" if (~ $v 0) {\n"); printf(" v=255\n"); printf(" } else {\n"); printf(" v=$dec($v)\n"); printf(" }\n"); printf(" s\n" "}\n" "\n"); } printf("fn o {\n" " f\n" " switch ($v) {\n"); { int i; for (i=0; i<256; i++) { if (i == 10 ) printf(" case %d\n\techo\n", i); else if (i == 27 ) printf(" case %d\n\techo -n '%c'\n", i, i); else if (i>= ' ' && i<= '~' && i != '\'') printf(" case %d\n\techo -n '%c'\n", i, i); else if (i == '\'') printf(" case %d\n\techo -n ''''\n", i); /* else * Missing characters can be generated using AWK if required. */ } } printf(" }\n" "}\n" "\n"); printf("fn i {\n"); printf(" f\n"); printf(" v=`{dd 'bs=1' 'count=1' >[2]/dev/null | od -t d1 | cut -d ' ' -s -f 2- }\n"); printf(" s\n"); printf("}\n" "\n"); if (MAXPRLE>1) { int i; printf("fn u2 { u ; u; }\n"); printf("fn d2 { d ; d; }\n"); printf("fn l2 { l ; l; }\n"); printf("fn r2 { r ; r; }\n"); printf("fn u3 { u2 ; u; }\n"); printf("fn d3 { d2 ; d; }\n"); printf("fn l3 { l2 ; l; }\n"); printf("fn r3 { r2 ; r; }\n"); for (i=4; i<=MAXPRLE; i++) { printf("fn u%d { u%d ; u%d; }\n", i, i-i/2, i/2); printf("fn d%d { d%d ; d%d; }\n", i, i-i/2, i/2); printf("fn l%d { l%d ; l%d; }\n", i, i-i/2, i/2); printf("fn r%d { r%d ; r%d; }\n", i, i-i/2, i/2); } } break; case '~': break; } }
/* For full structual optimisation (loops to multiplies) this function calls the outtxn function after finding '=' commands otherwise the commands are just pass to the BE. */ static void outopt(int ch, int count) { if (!enable_optim) outcmd(ch, count); else outtxn(ch, count); }
void pipe_to_be(char ** filelist, int filecount) { FILE * ifd; int ar, hashwarn = 0; for(ar=0; ar<filecount; ar++) { int ch, m, m0, inp=0, cmt=0, di = 0; int digits = 0, number = 0, ov_flg = 0, multi = 1; int qstring = 0; if (strcmp(filelist[ar], "-") == 0) { ifd = stdin; current_file = "stdin"; } else if((ifd = fopen(filelist[ar],"r")) == 0) { perror(filelist[ar]); exit(1); } else current_file = filelist[ar]; while((ch = getc(ifd)) != EOF && (ifd!=stdin || ch != '!' || !inp || qstring)) { /* Quoted strings are printed; do NOT set current cell) */ if (qstring) { if (ch == '"') { qstring++; if (qstring == 2) continue; if (qstring == 3) qstring = 1; } if (qstring == 2) { char * gs; qstring = 0; add_string(0); outcmd('"', 0); if ( (gs = get_string()) ) { /* The backend doesn't know about '"', save the * current cell then use it to print the string * before restoring it. */ outcmd('B', 0); while(*gs) { outcmd('=', *gs++); outcmd('.', 0); } outcmd('=', 0); outcmd('S', 0); } } else { add_string(ch); continue; } } /* Comments */ if (cmt || ch == '{') { cmt += (ch=='{') - (ch=='}'); continue; } /* Source RLE decoding */ if (ch >= '0' && ch <= '9') { digits = 1; number = ov_iadd(ov_imul(number, 10, &ov_flg), ch-'0', &ov_flg); continue; } if (ch == '~' && digits) { number = ov_ineg(number, &ov_flg); number = ov_iadd(number, -1, &ov_flg); continue; } if (ch == ' ' || ch == '\t') continue; if ( ov_flg ) number=digits=ov_flg=0; if (!di) { if (ch == '\n') continue; if (ch == '%' ) { if (number == 8) ; else if (number == 32 && be_interface.cells_are_ints) ; else if (number <= 32) { fprintf(stderr, "Bitsize of %d not supported for this backend.\n", number); exit(1); } bytecell = (number == 8); number = 0; digits = 0; continue; } if (ch == '>' && tapeinit <= 0) { tapeinit = number; number = 0; digits = 0; continue; } di = 1; outcmd('!', 0); } /* These chars have an argument. */ m = (ch == '>' || ch == '<' || ch == '+' || ch == '-' || ch == '=' || ch == 'N' || ch == 'M' || ch == 'C' || ch == 'D'); /* These ones do not */ m0 = (ch == '[' || ch == ']' || ch == '.' || ch == ',' || ch == 'I' || ch == 'E' || ch == 'B' || ch == 'S' || ch == 'T' || ch == 'V' || ch == 'W' || ch == '"' || ch == 'X' || ch == '*'); if (!m) { multi = 0; } else if (ch == '=') { if (!digits) number = 0; multi = number; } else { if (!digits) number = 1; multi = number; } number = 0; digits = 0; if (ch == '\n' || ch == '\f' || ch == '\a') continue; if(!m && !m0) { if (ch == '#') { if (!hashwarn) fprintf(stderr, "WARNING: Command '#' ignored by backend.\n"); hashwarn = 1; } else { if (ch > ' ' && ch <= '~') fprintf(stderr, "Command '%c' not supported\n", ch); else fprintf(stderr, "Command 0x%02x not supported\n", ch); exit(97); } } if (ch == '"') { qstring++; continue; } if (ch == ',') inp = 1; outcmd(ch, multi); } if (ifd != stdin) fclose(ifd); } outcmd('~', 0); }
void outopt(int ch, int count) { if (deadloop) { if (ch == '[') deadloop++; if (ch == ']') deadloop--; return; } if (ch == '[') { if (tape->is_set && tape->v == 0) { deadloop++; return; } } switch(ch) { case '[': case ']': case '!': case '~': case 'X': case '#': case 'I': case 'E': if (ch == '!') { flush_tape(1,0); tape->cleaned = tape->is_set = first_run = !disable_init_optim; } else if (ch == '~' && enable_optim && !disable_init_optim) flush_tape(1,0); else flush_tape(0,0); if (ch) outcmd(ch, count); /* Loops end with zero */ if (ch == ']') { tape->is_set = 1; tape->v = 0; tape->cleaned = 1; tape->cleaned_val = tape->v; } /* I could save the cleaned tape state at the beginning of a loop, * then when we find the matching end loop the two tapes could be * merged to give a tape of known values after the loop ends. * This would not break the pipeline style of this code. * * This would also give states where a cell is known to have one * of two or more different values. */ return; case '.': if (tape->is_set) { int c = tape->v; if (bytecell) c &= 0xFF; if (c > 0 && c < 128) { add_string(c); /* Limit the buffer size. */ if (sav_str_len >= 128*1024 - (tape->v=='\n')*1024) flush_string(); break; } } flush_tape(0,1); outcmd(ch, count); return; case ',': flush_tape(0,1); clear_cell(tape); outcmd(ch, count); return; case '>': while(count-->0) { if (tape->n == 0) new_n(tape); tape=tape->n; curroff++; } break; case '<': while(count-->0) { if (tape->p == 0) new_p(tape); tape=tape->p; curroff--; } break; case '+': if (be_interface.cells_are_ints || bytecell) { tape->v += count; if (bytecell) tape->v %= 256; /* -255..255 */ } else { int ov=0, res; res = ov_iadd(tape->v, count, &ov); if (!ov) tape->v = res; else { flush_tape(0,1); clear_cell(tape); outcmd(ch, count); } } break; case '-': if (be_interface.cells_are_ints || bytecell) { tape->v -= count; if (bytecell) tape->v %= 256; /* -255..255 */ } else { int ov=0, res; res = ov_isub(tape->v, count, &ov); if (!ov) tape->v = res; else { flush_tape(0,1); clear_cell(tape); outcmd(ch, count); } } break; case '=': tape->v = count; tape->is_set = 1; break; case 'B': flush_tape(0,1); if (be_interface.disable_be_optim) be_codegen_failure(); outcmd(ch, count); return; case 'M': case 'N': case 'S': case 'T': if (ch == 'N') count = -count; else if (ch == 'S') count = 1; else if (ch == 'T') count = -1; if (tape->is_set && tape->v == 0) { tape->is_set = 0 ; tape->v = 0; ch = 'C'; if (count == 1) ch = 'V'; else if (count == -1) { ch = 'W'; count = -count; } else if (count < 0) { ch = 'D'; count = -count; } } else { ch = 'M'; if (count == 1) ch = 'S'; else if (count == -1) { ch = 'T'; count = -count; } else if (count < 0) { ch = 'N'; count = -count; } } flush_tape(0,1); clear_cell(tape); if (be_interface.disable_be_optim) be_codegen_failure(); outcmd(ch, count); return; default: if (be_interface.disable_be_optim) be_codegen_failure(); if (ch>=0 && ch<256) fprintf(stderr, "Unknown token in bf2const.c (%d)\n", ch); flush_tape(0,0); outcmd(ch, count); return; } }
static void flush_tape(int no_output, int keep_knowns) { int outoff = 0, tapeoff = 0; int direction = 1; int flipcount = 2; struct mem *p; if (sav_str_len>0) flush_string(); p = tapezero; if(tapezero) { if (curroff > 0) direction = -1; for(;;) { if (no_output) clear_cell(p); if (bytecell) p->v %= 256; /* Note: preserves sign but limits range. */ if ((p->v || p->is_set) && (curroff != 0 || (tapeoff != 0 || flipcount == 0)) && (!keep_knowns || p == tape)) { if (p->cleaned && p->cleaned_val == p->v && p->is_set) { if (!keep_knowns) clear_cell(p); } else { if (tapeoff > outoff) { outcmd('>', tapeoff-outoff); outoff=tapeoff; } if (tapeoff < outoff) { outcmd('<', outoff-tapeoff); outoff=tapeoff; } if (p->is_set) { int c = p->v; if (bytecell) c &= 0xFF; outcmd('=', c); } else { if (p->v > 0) outcmd('+', p->v); if (p->v < 0) outcmd('-', -p->v); } if (keep_knowns && p->is_set) { p->cleaned = p->is_set; p->cleaned_val = p->v; } else clear_cell(p); } } if (direction > 0 && p->n) { p=p->n; tapeoff ++; } else if (direction < 0 && p->p) { p=p->p; tapeoff --; } else if (flipcount) { flipcount--; direction = -direction; } else break; } } if (no_output) outoff = curroff; if (curroff > outoff) { outcmd('>', curroff-outoff); outoff=curroff; } if (curroff < outoff) { outcmd('<', outoff-curroff); outoff=curroff; } if (!tapezero) tape = tapezero = calloc(1, sizeof*tape); if (!keep_knowns) { while(tape->p) tape = tape->p; while(tapezero->n) tapezero = tapezero->n; if (tape != tapezero) { tapezero->n = freelist; freelist = tape->n; tape->n = 0; } } tapezero = tape; curroff = 0; first_run = 0; }
void khTask::buildCommands(std::vector<std::vector<std::string> > &outcmds, const std::vector<Reservation> &res) { // My outputs have already been bound, now just do the variable // substitution in the command line // $OUTPUT -> alias for $OUTPUTS[0] // $OUTPUTS[<num>] // $OUTPUTS // $INPUT -> alias for $INPUTS[0] // $INPUTS[<num>] // $INPUTS // also handle :basename, :dirname, :sansext // extensions on variable names // $OUTPUT:sansext // $INPUTS[3]:dirname // Other possible substitutions // $NUMCPU -> number of CPUs assigned to the task std::vector<std::string> inputs; inputs.reserve(taskdef_.inputs.size()); for (std::vector<TaskDef::Input>::const_iterator i = taskdef_.inputs.begin(); i != taskdef_.inputs.end(); ++i) { inputs.push_back(i->path); } uint numcmds = taskdef_.commands.size(); #if 0 && defined(SUPPORT_TASK_RELOCATE) outcmds.resize(numcmds + relocateMap.size()); #else outcmds.resize(numcmds); #endif for (uint cmdnum = 0; cmdnum < numcmds; ++cmdnum) { std::vector<std::string> &outcmd(outcmds[cmdnum]); for (std::vector<std::string>::const_iterator arg = taskdef_.commands[cmdnum].begin(); arg != taskdef_.commands[cmdnum].end(); ++arg) { if (arg->empty()) continue; uint len = arg->size(); bool used = false; if ((*arg)[0] == '$') { const std::vector<std::string> *vec = 0; uint i = 0; if (StartsWith(*arg, "$OUTPUT")) { vec = &boundOutfiles; i = 7; } else if (StartsWith(*arg, "$INPUT")) { vec = &inputs; i = 6; } else if (*arg == "$NUMCPU") { uint numcpu = 0; for (std::vector<Reservation>::const_iterator r = res.begin(); r != res.end(); ++r) { const CPUReservationImpl *cpuimpl = dynamic_cast<const CPUReservationImpl*>(&**r); if (cpuimpl) { numcpu = cpuimpl->num(); break; } } if (numcpu == 0) { throw khException(kh::tr("Internal error: can find CPU reservation")); } outcmd.push_back(ToString(numcpu)); used = true; } if (vec) { int index = 0; if ((i < len) && ((*arg)[i] == 'S')) { ++i; if ((i < len) && ((*arg)[i] == '[')) { ++i; uint j = i; for (; j < len && ((*arg)[j] != ']'); ++j) ; if (j-i) { index = atoi(arg->substr(i, j-i).c_str()); } i = j+1; } else { // no subscript, we want them all index = -1; } } std::string (*adapter)(const std::string &) = &passthrough; if ((i+1 < len) && ((*arg)[i] == ':')) { std::string subcmd = arg->substr(i+1, std::string::npos); if (subcmd == "basename") adapter = &khBasename; else if (subcmd == "dirname") adapter = &khDirname; else if (subcmd == "sansext") adapter = &khDropExtension; else adapter = 0; } if (adapter) { used = true; if (index >= 0) { if (index < (int)vec->size()) { outcmd.push_back((*adapter)((*vec)[index])); } else { throw khException(kh::tr("Invalid commandline arg: %1") .arg(ToQString(*arg))); } } else { std::transform(vec->begin(), vec->end(), back_inserter(outcmd), adapter); } } } } if (!used) { outcmd.push_back(*arg); } } } /* for cmdnum */ #if 0 && defined(SUPPORT_TASK_RELOCATE) uint cmdnum = numcmds; for (std::map<std::string, std::string>::const_iterator reloc = relocateMap.begin(); reloc != relocateMap.end(); ++reloc) { std::vector<std::string> &outcmd(outcmds[cmdnum]); outcmd.resize(3); outcmd[0] = "khrelocate"; outcmd[1] = reloc->first; outcmd[2] = reloc->second; ++cmdnum; } #endif }
void threadmain(int argc, char *argv[]) { int i, got, scr; Text *t; Rectangle r; Flayer *nwhich; getscreen(argc, argv); iconinit(); initio(); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen->r; r.max.y = r.min.y+Dy(r)/5; flstart(screen->clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], gettext, 1, &cmd); flinit(&cmd.l[0], r, font, cmdcols); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; for(;;got = waitforio()){ if(hasunlocked && RESIZED()) resize(); if(got&(1<<RHost)) rcv(); if(got&(1<<RPlumb)){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RPlumb); } if(got&(1<<RKeyboard)) if(which) type(which, RKeyboard); else kbdblock(); if(got&(1<<RMouse)){ if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){ mouseunblock(); continue; } nwhich = flwhich(mousep->xy); scr = which && ptinrect(mousep->xy, which->scroll); if(mousep->buttons) flushtyping(1); if(mousep->buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) scroll(which, 1); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); } } }else if((mousep->buttons&2) && which){ if(scr) scroll(which, 2); else menu2hit(); }else if((mousep->buttons&4)){ if(scr) scroll(which, 3); else menu3hit(); } mouseunblock(); } } }
void threadmain(int argc, char *argv[]) { int i, got, scr, chord; Text *t; Rectangle r; Flayer *nwhich; /* * sam is talking to us on fd 0 and 1. * move these elsewhere so that if we accidentally * use 0 and 1 in other code, nothing bad happens. */ dup(0, 3); dup(1, 4); hostfd[0] = 3; hostfd[1] = 4; close(0); close(1); open("/dev/null", OREAD); if(open("/dev/tty", OWRITE) < 0) open("/dev/null", OWRITE); notify(notifyf); if(protodebug) print("getscreen\n"); getscreen(argc, argv); if(protodebug) print("iconinit\n"); iconinit(); if(protodebug) print("initio\n"); initio(); if(protodebug) print("scratch\n"); scratch = alloc(100*RUNESIZE); nscralloc = 100; r = screen->r; r.max.y = r.min.y+Dy(r)/5; if(protodebug) print("flstart\n"); flstart(screen->clipr); rinit(&cmd.rasp); flnew(&cmd.l[0], gettext, 1, &cmd); flinit(&cmd.l[0], r, font, cmdcols); cmd.nwin = 1; which = &cmd.l[0]; cmd.tag = Untagged; outTs(Tversion, VERSION); startnewfile(Tstartcmdfile, &cmd); got = 0; chord = 0; if(protodebug) print("loop\n"); for(;;got = waitforio()){ if(hasunlocked && RESIZED()) resize(); if(got&(1<<RHost)) rcv(); if(got&(1<<RPlumb)){ for(i=0; cmd.l[i].textfn==0; i++) ; current(&cmd.l[i]); flsetselect(which, cmd.rasp.nrunes, cmd.rasp.nrunes); type(which, RPlumb); } if(got&(1<<RKeyboard)) if(which) type(which, RKeyboard); else kbdblock(); if(got&(1<<RMouse)){ if(hostlock==2 || !ptinrect(mousep->xy, screen->r)){ mouseunblock(); continue; } nwhich = flwhich(mousep->xy); //scr = which && ptinrect(mousep->xy, which->scroll); scr = which && (ptinrect(mousep->xy, which->scroll) || mousep->buttons&(8|16)); if(mousep->buttons) flushtyping(1); //if(chording && chord==1 && !mousep->buttons) if((mousep->buttons&1)==0) chord = 0; //if(chording && chord) //chord |= mousep->buttons; //else if(mousep->buttons&1){ if(chord && which && which==nwhich){ chord |= mousep->buttons; t = (Text *)which->user1; if(!t->lock){ int w = which-t->l; if(chord&2){ cut(t, w, 1, 1); chord &= ~2; } if(chord&4){ paste(t, w); chord &= ~4; } } }else if(mousep->buttons&(1|8)){ //}else if(mousep->buttons&1){ if(nwhich){ if(nwhich!=which) current(nwhich); else if(scr) //scroll(which, 1); scroll(which, (mousep->buttons&8) ? 4 : 1); else{ t=(Text *)which->user1; if(flselect(which)){ outTsl(Tdclick, t->tag, which->p0); t->lock++; }else if(t!=&cmd) outcmd(); if(mousep->buttons&1) chord = mousep->buttons; } } }else if((mousep->buttons&2) && which){ if(scr) scroll(which, 2); else menu2hit(); }else if(mousep->buttons&(4|16)){ //}else if(mousep->buttons&4){ if(nwhich!=which) current(nwhich); else if(scr) //if(scr) //scroll(which, 3); scroll(which, (mousep->buttons&16) ? 5 : 3); else menu3hit(); } mouseunblock(); } } }
void outopt(int ch, int count) { if (deadloop) { if (ch == '[') deadloop++; if (ch == ']') deadloop--; return; } if (ch == '[' && enable_mov_optim) { if (tape->is_set && tape->v == 0) { deadloop++; return; } } switch(ch) { default: if (ch == '!') { flush_tape(1,0); tape->cleaned = tape->is_set = first_run = !disable_init_optim; } else if (ch == '~' && enable_optim && !disable_init_optim) flush_tape(1,0); else flush_tape(0,0); if (ch) outcmd(ch, count); /* Loops end with zero */ if (ch == ']') { tape->is_set = 1; tape->v = 0; tape->cleaned = 1; tape->cleaned_val = tape->v; } /* I could save the cleaned tape state at the beginning of a loop, * then when we find the matching end loop the two tapes could be * merged to give a tape of known values after the loop ends. * This would not break the pipeline style of this code. * * This would also give states where a cell is known to have one * of two or more different values. */ return; case '.': if (!disable_savestring && enable_be_optim && tape->is_set && tape->v > 0 && tape->v < 128) { add_string(tape->v); if (sav_str_len >= 128*1024) /* Limit the buffer size. */ { add_string(0); outcmd('"', 0); sav_str_len = 0; } break; } flush_tape(0,1); outcmd(ch, count); return; case ',': flush_tape(0,1); clear_cell(tape); outcmd(ch, count); return; case '>': while(count-->0) { if (tape->n == 0) new_n(tape); tape=tape->n; curroff++; } break; case '<': while(count-->0) { if (tape->p == 0) new_p(tape); tape=tape->p; curroff--; } break; case '+': tape->v += count; break; case '-': tape->v -= count; break; case '=': tape->v = count; tape->is_set = 1; break; case 'B': /* Some BE are not 32 bits, try to avoid cell size mistakes */ if (!cells_are_ints && (tape->v > 65536 || tape->v < -65536)) ; else if (tape->is_set) { if (bytecell) tape->v %= 256; /* Note: preserves sign but limits range. */ reg_known = 1; reg_val = tape->v; break; } flush_tape(0,1); reg_known = 0; reg_val = 0; if (enable_be_optim) { outcmd(ch, count); } else { outcmd('[', 1); } return; case 'M': case 'N': case 'S': case 'Q': case 'm': case 'n': case 's': case 'E': if (!reg_known) { flush_tape(0,1); clear_cell(tape); if (enable_be_optim) { outcmd(ch, count); } else switch(ch) { case 'M': case 'm': outcmd('+', count); break; case 'N': case 'n': outcmd('-', count); break; case 'S': case 's': outcmd('+', 1); break; case 'Q': outcmd('[', 1); outcmd('-', 1); outcmd(']', 1); if (count) outcmd('+', count); break; case 'E': outcmd(']', 1); break; } return; } switch(ch) { case 'm': case 'M': tape->v += reg_val * count; break; case 'n': case 'N': tape->v -= reg_val * count; break; case 's': case 'S': tape->v += reg_val; break; case 'Q': if (reg_val != 0) { tape->v = count; tape->is_set = 1; } break; } if (bytecell) tape->v %= 256; /* Note: preserves sign but limits range. */ } }