mesg.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
mesg.c (14442B) | |
--- | |
1 #include "sam.h" | |
2 Header h; | |
3 uchar indata[DATASIZE]; | |
4 uchar outdata[2*DATASIZE+3]; /* room for overflow message … | |
5 uchar *inp; | |
6 uchar *outp; | |
7 uchar *outmsg = outdata; | |
8 Posn cmdpt; | |
9 Posn cmdptadv; | |
10 Buffer snarfbuf; | |
11 int waitack; | |
12 int outbuffered; | |
13 int tversion; | |
14 | |
15 int inshort(void); | |
16 long inlong(void); | |
17 vlong invlong(void); | |
18 int inmesg(Tmesg); | |
19 | |
20 void outshort(int); | |
21 void outlong(long); | |
22 void outvlong(vlong); | |
23 void outcopy(int, void*); | |
24 void outsend(void); | |
25 void outstart(Hmesg); | |
26 | |
27 void setgenstr(File*, Posn, Posn); | |
28 | |
29 #ifdef DEBUG | |
30 char *hname[] = { | |
31 [Hversion] "Hversion", | |
32 [Hbindname] "Hbindname", | |
33 [Hcurrent] "Hcurrent", | |
34 [Hnewname] "Hnewname", | |
35 [Hmovname] "Hmovname", | |
36 [Hgrow] "Hgrow", | |
37 [Hcheck0] "Hcheck0", | |
38 [Hcheck] "Hcheck", | |
39 [Hunlock] "Hunlock", | |
40 [Hdata] "Hdata", | |
41 [Horigin] "Horigin", | |
42 [Hunlockfile] "Hunlockfile", | |
43 [Hsetdot] "Hsetdot", | |
44 [Hgrowdata] "Hgrowdata", | |
45 [Hmoveto] "Hmoveto", | |
46 [Hclean] "Hclean", | |
47 [Hdirty] "Hdirty", | |
48 [Hcut] "Hcut", | |
49 [Hsetpat] "Hsetpat", | |
50 [Hdelname] "Hdelname", | |
51 [Hclose] "Hclose", | |
52 [Hsetsnarf] "Hsetsnarf", | |
53 [Hsnarflen] "Hsnarflen", | |
54 [Hack] "Hack", | |
55 [Hexit] "Hexit", | |
56 // [Hplumb] "Hplumb" | |
57 }; | |
58 | |
59 char *tname[] = { | |
60 [Tversion] "Tversion", | |
61 [Tstartcmdfile] "Tstartcmdfile", | |
62 [Tcheck] "Tcheck", | |
63 [Trequest] "Trequest", | |
64 [Torigin] "Torigin", | |
65 [Tstartfile] "Tstartfile", | |
66 [Tworkfile] "Tworkfile", | |
67 [Ttype] "Ttype", | |
68 [Tcut] "Tcut", | |
69 [Tpaste] "Tpaste", | |
70 [Tsnarf] "Tsnarf", | |
71 [Tstartnewfile] "Tstartnewfile", | |
72 [Twrite] "Twrite", | |
73 [Tclose] "Tclose", | |
74 [Tlook] "Tlook", | |
75 [Tsearch] "Tsearch", | |
76 [Tsend] "Tsend", | |
77 [Tdclick] "Tdclick", | |
78 [Tstartsnarf] "Tstartsnarf", | |
79 [Tsetsnarf] "Tsetsnarf", | |
80 [Tack] "Tack", | |
81 [Texit] "Texit", | |
82 // [Tplumb] "Tplumb" | |
83 }; | |
84 | |
85 void | |
86 journal(int out, char *s) | |
87 { | |
88 static int fd = 0; | |
89 | |
90 if(fd <= 0) | |
91 fd = create("/tmp/sam.out", 1, 0666L); | |
92 fprint(fd, "%s%s\n", out? "out: " : "in: ", s); | |
93 } | |
94 | |
95 void | |
96 journaln(int out, long n) | |
97 { | |
98 char buf[32]; | |
99 | |
100 snprint(buf, sizeof buf, "%ld", n); | |
101 journal(out, buf); | |
102 } | |
103 | |
104 void | |
105 journalv(int out, vlong v) | |
106 { | |
107 char buf[32]; | |
108 | |
109 snprint(buf, sizeof buf, "%lld", v); | |
110 journal(out, buf); | |
111 } | |
112 | |
113 #else | |
114 #define journal(a, b) | |
115 #define journaln(a, b) | |
116 #endif | |
117 | |
118 int | |
119 rcvchar(void){ | |
120 static uchar buf[64]; | |
121 static int i, nleft = 0; | |
122 | |
123 if(nleft <= 0){ | |
124 nleft = read(0, (char *)buf, sizeof buf); | |
125 if(nleft <= 0) | |
126 return -1; | |
127 i = 0; | |
128 } | |
129 --nleft; | |
130 return buf[i++]; | |
131 } | |
132 | |
133 int | |
134 rcv(void){ | |
135 int c; | |
136 static int state = 0; | |
137 static int count = 0; | |
138 static int i = 0; | |
139 | |
140 while((c=rcvchar()) != -1) | |
141 switch(state){ | |
142 case 0: | |
143 h.type = c; | |
144 state++; | |
145 break; | |
146 | |
147 case 1: | |
148 h.count0 = c; | |
149 state++; | |
150 break; | |
151 | |
152 case 2: | |
153 h.count1 = c; | |
154 count = h.count0|(h.count1<<8); | |
155 i = 0; | |
156 if(count > DATASIZE) | |
157 panic("count>DATASIZE"); | |
158 if(count == 0) | |
159 goto zerocount; | |
160 state++; | |
161 break; | |
162 | |
163 case 3: | |
164 indata[i++] = c; | |
165 if(i == count){ | |
166 zerocount: | |
167 indata[i] = 0; | |
168 state = count = 0; | |
169 return inmesg(h.type); | |
170 } | |
171 break; | |
172 } | |
173 return 0; | |
174 } | |
175 | |
176 File * | |
177 whichfile(int tag) | |
178 { | |
179 int i; | |
180 | |
181 for(i = 0; i<file.nused; i++) | |
182 if(file.filepptr[i]->tag==tag) | |
183 return file.filepptr[i]; | |
184 hiccough((char *)0); | |
185 return 0; | |
186 } | |
187 | |
188 int | |
189 inmesg(Tmesg type) | |
190 { | |
191 Rune buf[1025]; | |
192 char cbuf[64]; | |
193 int i, m; | |
194 short s; | |
195 long l, l1; | |
196 vlong v; | |
197 File *f; | |
198 Posn p0, p1, p; | |
199 Range r; | |
200 String *str; | |
201 char *c, *wdir; | |
202 Rune *rp; | |
203 Plumbmsg *pm; | |
204 | |
205 if(type > TMAX) | |
206 panic("inmesg"); | |
207 | |
208 journal(0, tname[type]); | |
209 | |
210 inp = indata; | |
211 switch(type){ | |
212 case -1: | |
213 panic("rcv error"); | |
214 | |
215 default: | |
216 fprint(2, "unknown type %d\n", type); | |
217 panic("rcv unknown"); | |
218 | |
219 case Tversion: | |
220 tversion = inshort(); | |
221 journaln(0, tversion); | |
222 break; | |
223 | |
224 case Tstartcmdfile: | |
225 v = invlong(); /* for 64-bit pointers */ | |
226 journaln(0, v); | |
227 Strdupl(&genstr, samname); | |
228 cmd = newfile(); | |
229 cmd->unread = 0; | |
230 outTsv(Hbindname, cmd->tag, v); | |
231 outTs(Hcurrent, cmd->tag); | |
232 logsetname(cmd, &genstr); | |
233 cmd->rasp = listalloc('P'); | |
234 cmd->mod = 0; | |
235 if(cmdstr.n){ | |
236 loginsert(cmd, 0L, cmdstr.s, cmdstr.n); | |
237 Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); | |
238 } | |
239 fileupdate(cmd, FALSE, TRUE); | |
240 outT0(Hunlock); | |
241 break; | |
242 | |
243 case Tcheck: | |
244 /* go through whichfile to check the tag */ | |
245 outTs(Hcheck, whichfile(inshort())->tag); | |
246 break; | |
247 | |
248 case Trequest: | |
249 f = whichfile(inshort()); | |
250 p0 = inlong(); | |
251 p1 = p0+inshort(); | |
252 journaln(0, p0); | |
253 journaln(0, p1-p0); | |
254 if(f->unread) | |
255 panic("Trequest: unread"); | |
256 if(p1>f->b.nc) | |
257 p1 = f->b.nc; | |
258 if(p0>f->b.nc) /* can happen e.g. scrolling during comma… | |
259 p0 = f->b.nc; | |
260 if(p0 == p1){ | |
261 i = 0; | |
262 r.p1 = r.p2 = p0; | |
263 }else{ | |
264 r = rdata(f->rasp, p0, p1-p0); | |
265 i = r.p2-r.p1; | |
266 bufread(&f->b, r.p1, buf, i); | |
267 } | |
268 buf[i]=0; | |
269 outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); | |
270 break; | |
271 | |
272 case Torigin: | |
273 s = inshort(); | |
274 l = inlong(); | |
275 l1 = inlong(); | |
276 journaln(0, l1); | |
277 lookorigin(whichfile(s), l, l1); | |
278 break; | |
279 | |
280 case Tstartfile: | |
281 termlocked++; | |
282 f = whichfile(inshort()); | |
283 if(!f->rasp) /* this might be a duplicate message… | |
284 f->rasp = listalloc('P'); | |
285 current(f); | |
286 outTsv(Hbindname, f->tag, invlong()); /* for 64-b… | |
287 outTs(Hcurrent, f->tag); | |
288 journaln(0, f->tag); | |
289 if(f->unread) | |
290 load(f); | |
291 else{ | |
292 if(f->b.nc>0){ | |
293 rgrow(f->rasp, 0L, f->b.nc); | |
294 outTsll(Hgrow, f->tag, 0L, f->b.nc); | |
295 } | |
296 outTs(Hcheck0, f->tag); | |
297 moveto(f, f->dot.r); | |
298 } | |
299 break; | |
300 | |
301 case Tworkfile: | |
302 i = inshort(); | |
303 f = whichfile(i); | |
304 current(f); | |
305 f->dot.r.p1 = inlong(); | |
306 f->dot.r.p2 = inlong(); | |
307 f->tdot = f->dot.r; | |
308 journaln(0, i); | |
309 journaln(0, f->dot.r.p1); | |
310 journaln(0, f->dot.r.p2); | |
311 break; | |
312 | |
313 case Ttype: | |
314 f = whichfile(inshort()); | |
315 p0 = inlong(); | |
316 journaln(0, p0); | |
317 journal(0, (char*)inp); | |
318 str = tmpcstr((char*)inp); | |
319 i = str->n; | |
320 loginsert(f, p0, str->s, str->n); | |
321 if(fileupdate(f, FALSE, FALSE)) | |
322 seq++; | |
323 if(f==cmd && p0==f->b.nc-i && i>0 && str->s[i-1]=='\n'){ | |
324 freetmpstr(str); | |
325 termlocked++; | |
326 termcommand(); | |
327 }else | |
328 freetmpstr(str); | |
329 f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this… | |
330 f->tdot = f->dot.r; | |
331 break; | |
332 | |
333 case Tcut: | |
334 f = whichfile(inshort()); | |
335 p0 = inlong(); | |
336 p1 = inlong(); | |
337 journaln(0, p0); | |
338 journaln(0, p1); | |
339 logdelete(f, p0, p1); | |
340 if(fileupdate(f, FALSE, FALSE)) | |
341 seq++; | |
342 f->dot.r.p1 = f->dot.r.p2 = p0; | |
343 f->tdot = f->dot.r; /* terminal knows the value of dot… | |
344 break; | |
345 | |
346 case Tpaste: | |
347 f = whichfile(inshort()); | |
348 p0 = inlong(); | |
349 journaln(0, p0); | |
350 for(l=0; l<snarfbuf.nc; l+=m){ | |
351 m = snarfbuf.nc-l; | |
352 if(m>BLOCKSIZE) | |
353 m = BLOCKSIZE; | |
354 bufread(&snarfbuf, l, genbuf, m); | |
355 loginsert(f, p0, tmprstr(genbuf, m)->s, m); | |
356 } | |
357 if(fileupdate(f, FALSE, TRUE)) | |
358 seq++; | |
359 f->dot.r.p1 = p0; | |
360 f->dot.r.p2 = p0+snarfbuf.nc; | |
361 f->tdot.p1 = -1; /* force telldot to tell (arguably a BU… | |
362 telldot(f); | |
363 outTs(Hunlockfile, f->tag); | |
364 break; | |
365 | |
366 case Tsnarf: | |
367 i = inshort(); | |
368 p0 = inlong(); | |
369 p1 = inlong(); | |
370 snarf(whichfile(i), p0, p1, &snarfbuf, 0); | |
371 break; | |
372 | |
373 case Tstartnewfile: | |
374 v = invlong(); | |
375 Strdupl(&genstr, empty); | |
376 f = newfile(); | |
377 f->rasp = listalloc('P'); | |
378 outTsv(Hbindname, f->tag, v); | |
379 logsetname(f, &genstr); | |
380 outTs(Hcurrent, f->tag); | |
381 current(f); | |
382 load(f); | |
383 break; | |
384 | |
385 case Twrite: | |
386 termlocked++; | |
387 i = inshort(); | |
388 journaln(0, i); | |
389 f = whichfile(i); | |
390 addr.r.p1 = 0; | |
391 addr.r.p2 = f->b.nc; | |
392 if(f->name.s[0] == 0) | |
393 error(Enoname); | |
394 Strduplstr(&genstr, &f->name); | |
395 writef(f); | |
396 break; | |
397 | |
398 case Tclose: | |
399 termlocked++; | |
400 i = inshort(); | |
401 journaln(0, i); | |
402 f = whichfile(i); | |
403 current(f); | |
404 trytoclose(f); | |
405 /* if trytoclose fails, will error out */ | |
406 delete(f); | |
407 break; | |
408 | |
409 case Tlook: | |
410 f = whichfile(inshort()); | |
411 termlocked++; | |
412 p0 = inlong(); | |
413 p1 = inlong(); | |
414 journaln(0, p0); | |
415 journaln(0, p1); | |
416 setgenstr(f, p0, p1); | |
417 for(l = 0; l<genstr.n; l++){ | |
418 i = genstr.s[l]; | |
419 if(utfrune(".*+?(|)\\[]^$", i)){ | |
420 str = tmpcstr("\\"); | |
421 Strinsert(&genstr, str, l++); | |
422 freetmpstr(str); | |
423 } | |
424 } | |
425 Straddc(&genstr, '\0'); | |
426 nextmatch(f, &genstr, p1, 1); | |
427 moveto(f, sel.p[0]); | |
428 break; | |
429 | |
430 case Tsearch: | |
431 termlocked++; | |
432 if(curfile == 0) | |
433 error(Enofile); | |
434 if(lastpat.s[0] == 0) | |
435 panic("Tsearch"); | |
436 nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); | |
437 moveto(curfile, sel.p[0]); | |
438 break; | |
439 | |
440 case Tsend: | |
441 termlocked++; | |
442 inshort(); /* ignored */ | |
443 p0 = inlong(); | |
444 p1 = inlong(); | |
445 setgenstr(cmd, p0, p1); | |
446 bufreset(&snarfbuf); | |
447 bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n); | |
448 outTl(Hsnarflen, genstr.n); | |
449 if(genstr.s[genstr.n-1] != '\n') | |
450 Straddc(&genstr, '\n'); | |
451 loginsert(cmd, cmd->b.nc, genstr.s, genstr.n); | |
452 fileupdate(cmd, FALSE, TRUE); | |
453 cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->b.nc; | |
454 telldot(cmd); | |
455 termcommand(); | |
456 break; | |
457 | |
458 case Tdclick: | |
459 f = whichfile(inshort()); | |
460 p1 = inlong(); | |
461 doubleclick(f, p1); | |
462 f->tdot.p1 = f->tdot.p2 = p1; | |
463 telldot(f); | |
464 outTs(Hunlockfile, f->tag); | |
465 break; | |
466 | |
467 case Tstartsnarf: | |
468 if (snarfbuf.nc <= 0) { /* nothing to export */ | |
469 outTs(Hsetsnarf, 0); | |
470 break; | |
471 } | |
472 c = 0; | |
473 i = 0; | |
474 m = snarfbuf.nc; | |
475 if(m > SNARFSIZE) { | |
476 m = SNARFSIZE; | |
477 dprint("?warning: snarf buffer truncated\n"); | |
478 } | |
479 rp = malloc(m*sizeof(Rune)); | |
480 if(rp){ | |
481 bufread(&snarfbuf, 0, rp, m); | |
482 c = Strtoc(tmprstr(rp, m)); | |
483 free(rp); | |
484 i = strlen(c); | |
485 } | |
486 outTs(Hsetsnarf, i); | |
487 if(c){ | |
488 Write(1, c, i); | |
489 free(c); | |
490 } else | |
491 dprint("snarf buffer too long\n"); | |
492 break; | |
493 | |
494 case Tsetsnarf: | |
495 m = inshort(); | |
496 if(m > SNARFSIZE) | |
497 error(Etoolong); | |
498 c = malloc(m+1); | |
499 if(c){ | |
500 for(i=0; i<m; i++) | |
501 c[i] = rcvchar(); | |
502 c[m] = 0; | |
503 str = tmpcstr(c); | |
504 free(c); | |
505 bufreset(&snarfbuf); | |
506 bufinsert(&snarfbuf, (Posn)0, str->s, str->n); | |
507 freetmpstr(str); | |
508 outT0(Hunlock); | |
509 } | |
510 break; | |
511 | |
512 case Tack: | |
513 waitack = 0; | |
514 break; | |
515 #if 0 | |
516 case Tplumb: | |
517 f = whichfile(inshort()); | |
518 p0 = inlong(); | |
519 p1 = inlong(); | |
520 pm = emalloc(sizeof(Plumbmsg)); | |
521 pm->src = strdup("sam"); | |
522 pm->dst = 0; | |
523 /* construct current directory */ | |
524 c = Strtoc(&f->name); | |
525 if(c[0] == '/') | |
526 pm->wdir = c; | |
527 else{ | |
528 wdir = emalloc(1024); | |
529 getwd(wdir, 1024); | |
530 pm->wdir = emalloc(1024); | |
531 snprint(pm->wdir, 1024, "%s/%s", wdir, c); | |
532 cleanname(pm->wdir); | |
533 free(wdir); | |
534 free(c); | |
535 } | |
536 c = strrchr(pm->wdir, '/'); | |
537 if(c) | |
538 *c = '\0'; | |
539 pm->type = strdup("text"); | |
540 if(p1 > p0) | |
541 pm->attr = nil; | |
542 else{ | |
543 p = p0; | |
544 while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i… | |
545 p0--; | |
546 while(p1<f->b.nc && (i=filereadc(f, p1))!=' ' &&… | |
547 p1++; | |
548 sprint(cbuf, "click=%ld", p-p0); | |
549 pm->attr = plumbunpackattr(cbuf); | |
550 } | |
551 if(p0==p1 || p1-p0>=BLOCKSIZE){ | |
552 plumbfree(pm); | |
553 break; | |
554 } | |
555 setgenstr(f, p0, p1); | |
556 pm->data = Strtoc(&genstr); | |
557 pm->ndata = strlen(pm->data); | |
558 c = plumbpack(pm, &i); | |
559 if(c != 0){ | |
560 outTs(Hplumb, i); | |
561 Write(1, c, i); | |
562 free(c); | |
563 } | |
564 plumbfree(pm); | |
565 break; | |
566 #endif | |
567 case Texit: | |
568 exits(0); | |
569 } | |
570 return TRUE; | |
571 } | |
572 | |
573 void | |
574 snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok) | |
575 { | |
576 Posn l; | |
577 int i; | |
578 | |
579 if(!emptyok && p1==p2) | |
580 return; | |
581 bufreset(buf); | |
582 /* Stage through genbuf to avoid compaction problems (vestigial)… | |
583 if(p2 > f->b.nc){ | |
584 fprint(2, "bad snarf addr p1=%ld p2=%ld f->b.nc=%d\n", p… | |
585 p2 = f->b.nc; | |
586 } | |
587 for(l=p1; l<p2; l+=i){ | |
588 i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l; | |
589 bufread(&f->b, l, genbuf, i); | |
590 bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i); | |
591 } | |
592 } | |
593 | |
594 int | |
595 inshort(void) | |
596 { | |
597 ushort n; | |
598 | |
599 n = inp[0] | (inp[1]<<8); | |
600 inp += 2; | |
601 return n; | |
602 } | |
603 | |
604 long | |
605 inlong(void) | |
606 { | |
607 ulong n; | |
608 | |
609 n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24); | |
610 inp += 4; | |
611 return n; | |
612 } | |
613 | |
614 vlong | |
615 invlong(void) | |
616 { | |
617 vlong v; | |
618 | |
619 v = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4]; | |
620 v = (v<<16) | (inp[3]<<8) | inp[2]; | |
621 v = (v<<16) | (inp[1]<<8) | inp[0]; | |
622 inp += 8; | |
623 return v; | |
624 } | |
625 | |
626 void | |
627 setgenstr(File *f, Posn p0, Posn p1) | |
628 { | |
629 if(p0 != p1){ | |
630 if(p1-p0 >= TBLOCKSIZE) | |
631 error(Etoolong); | |
632 Strinsure(&genstr, p1-p0); | |
633 bufread(&f->b, p0, genbuf, p1-p0); | |
634 memmove(genstr.s, genbuf, RUNESIZE*(p1-p0)); | |
635 genstr.n = p1-p0; | |
636 }else{ | |
637 if(snarfbuf.nc == 0) | |
638 error(Eempty); | |
639 if(snarfbuf.nc > TBLOCKSIZE) | |
640 error(Etoolong); | |
641 bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc); | |
642 Strinsure(&genstr, snarfbuf.nc); | |
643 memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc); | |
644 genstr.n = snarfbuf.nc; | |
645 } | |
646 } | |
647 | |
648 void | |
649 outT0(Hmesg type) | |
650 { | |
651 outstart(type); | |
652 outsend(); | |
653 } | |
654 | |
655 void | |
656 outTl(Hmesg type, long l) | |
657 { | |
658 outstart(type); | |
659 outlong(l); | |
660 outsend(); | |
661 } | |
662 | |
663 void | |
664 outTs(Hmesg type, int s) | |
665 { | |
666 outstart(type); | |
667 journaln(1, s); | |
668 outshort(s); | |
669 outsend(); | |
670 } | |
671 | |
672 void | |
673 outS(String *s) | |
674 { | |
675 char *c; | |
676 int i; | |
677 | |
678 c = Strtoc(s); | |
679 i = strlen(c); | |
680 outcopy(i, c); | |
681 if(i > 99) | |
682 c[99] = 0; | |
683 journaln(1, i); | |
684 journal(1, c); | |
685 free(c); | |
686 } | |
687 | |
688 void | |
689 outTsS(Hmesg type, int s1, String *s) | |
690 { | |
691 outstart(type); | |
692 outshort(s1); | |
693 outS(s); | |
694 outsend(); | |
695 } | |
696 | |
697 void | |
698 outTslS(Hmesg type, int s1, Posn l1, String *s) | |
699 { | |
700 outstart(type); | |
701 outshort(s1); | |
702 journaln(1, s1); | |
703 outlong(l1); | |
704 journaln(1, l1); | |
705 outS(s); | |
706 outsend(); | |
707 } | |
708 | |
709 void | |
710 outTS(Hmesg type, String *s) | |
711 { | |
712 outstart(type); | |
713 outS(s); | |
714 outsend(); | |
715 } | |
716 | |
717 void | |
718 outTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s) | |
719 { | |
720 outstart(type); | |
721 outshort(s1); | |
722 outlong(l1); | |
723 outlong(l2); | |
724 journaln(1, l1); | |
725 journaln(1, l2); | |
726 outS(s); | |
727 outsend(); | |
728 } | |
729 | |
730 void | |
731 outTsll(Hmesg type, int s, Posn l1, Posn l2) | |
732 { | |
733 outstart(type); | |
734 outshort(s); | |
735 outlong(l1); | |
736 outlong(l2); | |
737 journaln(1, l1); | |
738 journaln(1, l2); | |
739 outsend(); | |
740 } | |
741 | |
742 void | |
743 outTsl(Hmesg type, int s, Posn l) | |
744 { | |
745 outstart(type); | |
746 outshort(s); | |
747 outlong(l); | |
748 journaln(1, l); | |
749 outsend(); | |
750 } | |
751 | |
752 void | |
753 outTsv(Hmesg type, int s, vlong v) | |
754 { | |
755 outstart(type); | |
756 outshort(s); | |
757 outvlong(v); | |
758 journaln(1, v); | |
759 outsend(); | |
760 } | |
761 | |
762 void | |
763 outstart(Hmesg type) | |
764 { | |
765 journal(1, hname[type]); | |
766 outmsg[0] = type; | |
767 outp = outmsg+3; | |
768 } | |
769 | |
770 void | |
771 outcopy(int count, void *data) | |
772 { | |
773 memmove(outp, data, count); | |
774 outp += count; | |
775 } | |
776 | |
777 void | |
778 outshort(int s) | |
779 { | |
780 *outp++ = s; | |
781 *outp++ = s>>8; | |
782 } | |
783 | |
784 void | |
785 outlong(long l) | |
786 { | |
787 *outp++ = l; | |
788 *outp++ = l>>8; | |
789 *outp++ = l>>16; | |
790 *outp++ = l>>24; | |
791 } | |
792 | |
793 void | |
794 outvlong(vlong v) | |
795 { | |
796 int i; | |
797 | |
798 for(i = 0; i < 8; i++){ | |
799 *outp++ = v; | |
800 v >>= 8; | |
801 } | |
802 } | |
803 | |
804 void | |
805 outsend(void) | |
806 { | |
807 int outcount; | |
808 | |
809 if(outp >= outdata+nelem(outdata)) | |
810 panic("outsend"); | |
811 outcount = outp-outmsg; | |
812 outcount -= 3; | |
813 outmsg[1] = outcount; | |
814 outmsg[2] = outcount>>8; | |
815 outmsg = outp; | |
816 if(!outbuffered){ | |
817 outcount = outmsg-outdata; | |
818 if (write(1, (char*) outdata, outcount) != outcount) | |
819 rescue(); | |
820 outmsg = outdata; | |
821 return; | |
822 } | |
823 } | |
824 | |
825 int | |
826 needoutflush(void) | |
827 { | |
828 return outmsg >= outdata+DATASIZE; | |
829 } | |
830 | |
831 void | |
832 outflush(void) | |
833 { | |
834 if(outmsg == outdata) | |
835 return; | |
836 outbuffered = 0; | |
837 /* flow control */ | |
838 outT0(Hack); | |
839 waitack = 1; | |
840 do | |
841 if(rcv() == 0){ | |
842 rescue(); | |
843 exits("eof"); | |
844 } | |
845 while(waitack); | |
846 outmsg = outdata; | |
847 outbuffered = 1; | |
848 } |