xref: /original-bsd/usr.bin/tn3270/tools/prt3270.c (revision 08a536bc)
1 /*
2  *	Copyright (c) 1984-1987 by the Regents of the
3  *	University of California and by Gregory Glenn Minshall.
4  *
5  *	Permission to use, copy, modify, and distribute these
6  *	programs and their documentation for any purpose and
7  *	without fee is hereby granted, provided that this
8  *	copyright and permission appear on all copies and
9  *	supporting documentation, the name of the Regents of
10  *	the University of California not be used in advertising
11  *	or publicity pertaining to distribution of the programs
12  *	without specific prior permission, and notice be given in
13  *	supporting documentation that copying and distribution is
14  *	by permission of the Regents of the University of California
15  *	and by Gregory Glenn Minshall.  Neither the Regents of the
16  *	University of California nor Gregory Glenn Minshall make
17  *	representations about the suitability of this software
18  *	for any purpose.  It is provided "as is" without
19  *	express or implied warranty.
20  */
21 
22 #ifndef lint
23 static char sccsid[] = "@(#)prt3270.c	3.1 (Berkeley) 08/11/87";
24 #endif	/* not lint */
25 
26 #if defined(unix)
27 #endif
28 #include <stdio.h>
29 #include <ctype.h>
30 
31 #include "../general/general.h"
32 
33 #include "../api/asc_ebc.h"
34 #include "../ctlr/hostctlr.h"
35 #include "../ctlr/screen.h"
36 #include "../ctlr/function.h"
37 #include "../api/astosc.h"
38 #include "../general/globals.h"
39 
40 #include "../ctlr/kbd.out"
41 
42 
43 int NumberColumns = 80;
44 
45 int direction;
46 
47 int column = 1;
48 int indenting = 0;
49 int direction = '?';
50 
51 unsigned char printBuffer[200], *print = printBuffer;
52 
53 #define	ColsLeft()	(79-column)	/* A little room for error */
54 
55 
56 void
57 putSpace()
58 {
59     extern void Column1();
60     unsigned char *ourPrint = print;
61 
62     print = printBuffer;		/* For mutual calls */
63     *ourPrint = 0;
64     if (ColsLeft() < 0) {
65 	Column1();
66     }
67     if (column != (indenting*8+1)) {
68 	putchar(' ');
69     } else {
70 	int i;
71 
72 	putchar(direction);
73 	putchar(' ');
74 	for (i = 0; i < indenting; i++) {
75 	    putchar('\t');
76 	}
77     }
78     printf("%s", printBuffer);
79     column += strlen(printBuffer);
80 }
81 
82 void
83 Column1()
84 {
85     if (print != printBuffer) {
86 	putSpace();
87     }
88     if (column != (indenting*8+1)) {
89 	putchar('\n');
90 	column = indenting*8+1;
91     }
92 }
93 
94 void
95 Indent()
96 {
97     if ((column != (indenting*8+1)) || (print != printBuffer)) {
98 	Column1();
99     }
100     indenting++;
101     column = indenting*8+1;
102 }
103 
104 void
105 Undent()
106 {
107     if ((column != (indenting*8+1)) || (print != printBuffer)) {
108 	Column1();
109     }
110     indenting--;
111     if (indenting < 0) {
112 	fflush(stdout);
113 	fprintf(stderr, "INTERNAL ERROR: indenting < 0.\n");
114 	fflush(stderr);
115     } else {
116 	column = indenting*8+1;
117     }
118 }
119 
120 void
121 putChar(character)
122 int	character;
123 {
124     *print++ = character;
125     column++;
126 }
127 
128 void
129 putstr(s)
130 char *s;
131 {
132     while (*s) {
133 	putChar(*s++);
134     }
135 }
136 
137 void
138 put2hex(i)
139 int i;
140 {
141     char place[40];
142 
143     sprintf(place, "%02x", i);
144     putstr(place);
145 }
146 
147 
148 void
149 putdecimal(i)
150 int i;
151 {
152     char place[40];
153 
154     sprintf(place, "%d", i);
155     putstr(place);
156 }
157 
158 void
159 puthex(i)
160 int i;
161 {
162     char place[40];
163 
164     sprintf(place, "%x", i);
165     putstr(place);
166 }
167 
168 void
169 putEChar(character)
170 int character;
171 {
172     putChar(ebc_asc[character]);
173     if (ColsLeft() < 10) {
174 	Column1();
175     }
176 }
177 
178 void
179 PrintAid(i)
180 int	i;
181 {
182     struct astosc *this;
183 
184     for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) {
185 	if (this->function == FCN_AID) {
186 	    int j;
187 
188 	    switch (this->shiftstate) {
189 	    case 0:
190 		j = 0;
191 		break;
192 	    case SHIFT_UPSHIFT:
193 		j = 1;
194 		break;
195 	    case SHIFT_ALT:
196 		j = 2;
197 		break;
198 	    case (SHIFT_UPSHIFT|SHIFT_ALT):
199 		j = 3;
200 		break;
201 	    default:
202 		fprintf(stderr, "Bad shiftstate 0x%x.\n", this->shiftstate);
203 		exit(1);
204 	    }
205 	    if (hits[this->scancode].hit[j].code == i) {
206 		putstr(this->name);
207 		return;
208 	    }
209 	}
210     }
211 
212     putstr("Unknown AID 0x");
213     put2hex(i);
214 }
215 
216 void
217 PrintAddr(i)
218 int	i;
219 {
220     if (ColsLeft() < 9) {
221 	Column1();
222     }
223     putChar('(');
224     putdecimal(ScreenLine(i));
225     putChar(',');
226     putdecimal(ScreenLineOffset(i));
227     putChar(')');
228 }
229 
230 
231 /* returns the number of characters consumed */
232 int
233 DataFromNetwork(buffer, count, control)
234 register unsigned char	*buffer;		/* what the data is */
235 register int	count;				/* and how much there is */
236 int	control;				/* this buffer ended block? */
237 {
238     int origCount;
239     register int c;
240     register int i;
241     static int Command;
242     static int Wcc;
243     static int	LastWasTerminated = 1;	/* was "control" = 1 last time? */
244 
245     if (count == 0) {
246 	Column1();
247 	return 0;
248     }
249 
250     origCount = count;
251 
252     if (LastWasTerminated) {
253 
254 	if (count < 2) {
255 	    if (count == 0) {
256 		fflush(stdout);
257 		fprintf(stderr, "Short count received from host!\n");
258 		fflush(stderr);
259 		return(count);
260 	    }
261 	    Command = buffer[0];
262 	    switch (Command) {		/* This had better be a read command */
263 	    case CMD_READ_MODIFIED:
264 		putstr("read_modified command\n");
265 		break;
266 	    case CMD_SNA_READ_MODIFIED:
267 		putstr("read_modified command\n");
268 		break;
269 	    case CMD_SNA_READ_MODIFIED_ALL:
270 		putstr("read_modified command\n");
271 		break;
272 	    case CMD_READ_BUFFER:
273 		putstr("read_modified command\n");
274 		break;
275 	    case CMD_SNA_READ_BUFFER:
276 		putstr("read_modified command\n");
277 		break;
278 	    default:
279 		break;
280 	    }
281 	    return(1);			/* We consumed everything */
282 	}
283 	Command = buffer[0];
284 	Wcc = buffer[1];
285 	switch (Command) {
286 	case CMD_ERASE_WRITE:
287 	    putstr("erase write command ");
288 	    break;
289 	case CMD_ERASE_WRITE_ALTERNATE:
290 	    putstr("erase write alternate command ");
291 	    break;
292 	case CMD_SNA_ERASE_WRITE:
293 	    putstr("sna erase write command ");
294 	    break;
295 	case CMD_SNA_ERASE_WRITE_ALTERNATE:
296 	    putstr("erase write alternate command ");
297 	    break;
298 	case CMD_ERASE_ALL_UNPROTECTED:
299 	    putstr("erase all unprotected command ");
300 	    break;
301 	case CMD_SNA_ERASE_ALL_UNPROTECTED:
302 	    putstr("sna erase write command ");
303 	    break;
304 	case CMD_WRITE:
305 	    putstr("write command ");
306 	    break;
307 	case CMD_SNA_WRITE:
308 	    putstr("sna write command ");
309 	    break;
310 	default:
311 	    putstr("Unexpected command code 0x");
312 	    puthex(Command);
313 	    putstr(" received.");
314 	    Column1();
315 	    break;
316 	}
317 	putstr("WCC is 0x");
318 	puthex(Wcc);
319 	Column1();
320 
321 	count -= 2;			/* strip off command and wcc */
322 	buffer += 2;
323 
324     }
325     LastWasTerminated = 0;		/* then, reset at end... */
326 
327     while (count) {
328 	count--;
329 	c = *buffer++;
330 	if (IsOrder(c)) {
331 	    /* handle an order */
332 	    switch (c) {
333 #		define Ensure(x)	if (count < x) { \
334 					    if (!control) { \
335 						return(origCount-(count+1)); \
336 					    } else { \
337 						/* XXX - should not occur */ \
338 						count = 0; \
339 						break; \
340 					    } \
341 					}
342 	    case ORDER_SF:
343 		Ensure(1);
344 		c = *buffer++;
345 		count--;
346 		putstr("SF (0x");
347 		put2hex(c);
348 		putstr(") ");
349 		break;
350 	    case ORDER_SBA:
351 		Ensure(2);
352 		i = buffer[0];
353 		c = buffer[1];
354 		buffer += 2;
355 		count -= 2;
356 		putstr("SBA to ");
357 		PrintAddr(Addr3270(i,c));
358 		putSpace();
359 		break;
360 	    case ORDER_IC:
361 		putstr("IC");
362 		putSpace();
363 		break;
364 	    case ORDER_PT:
365 		putstr("PT");
366 		putSpace();
367 		break;
368 	    case ORDER_RA:
369 		Ensure(3);
370 		i = Addr3270(buffer[0], buffer[1]);
371 		c = buffer[2];
372 		buffer += 3;
373 		count -= 3;
374 		putstr("RA to ");
375 		PrintAddr(i);
376 		putstr(" of 0x");
377 		put2hex(c);
378 		putSpace();
379 		break;
380 	    case ORDER_EUA:    /* (from [here,there), ie: half open interval] */
381 		Ensure(2);
382 		putstr("EUA to ");
383 		PrintAddr(Addr3270(buffer[0], buffer[1]));
384 		putSpace();
385 		buffer += 2;
386 		count -= 2;
387 		break;
388 	    case ORDER_YALE:		/* special YALE defined order */
389 		Ensure(2);	/* need at least two characters */
390 		putstr("YALE order");
391 		putSpace();
392 		break;
393 	    default:
394 		putstr("UNKNOWN ORDER: 0x");
395 		put2hex(c);
396 		putSpace();
397 		break;
398 	    }
399 	    if (count < 0) {
400 		count = 0;
401 	    }
402 	} else {
403 	    /* Data comes in large clumps - take it all */
404 	    putstr("DATA:");
405 	    Indent();
406 	    putEChar(c);
407 	    c = *buffer;
408 	    while (count && !IsOrder(c)) {
409 		putEChar(c);
410 		count--;
411 		buffer++;
412 		c = *buffer;
413 	    }
414 	    Undent();
415 	}
416     }
417     LastWasTerminated = control;
418     return origCount - count;
419 }
420 
421 int
422 DataToNetwork(buffer, count, control)
423 unsigned char *buffer;
424 int count;
425 int control;
426 {
427 #define	NEED_AID	0
428 #define	JUST_GOT_AID	1
429 #define	DATA		2
430 #define	DATA_CONTINUE	3
431     static int state = NEED_AID;
432     static int aid;
433     int origCount = count;
434 
435     if (count == 0) {
436 	if (control) {
437 	    state = NEED_AID;
438 	}
439 	Column1();
440 	return 0;
441     }
442 
443     switch (state) {
444     case NEED_AID:
445 	aid = buffer[0];
446 	buffer++;
447 	count--;
448 	PrintAid(aid);
449 	putSpace();
450 	if (aid == AID_TREQ) {
451 	    state = DATA;
452 	} else {
453 	    state = JUST_GOT_AID;
454 	}
455 	return origCount - count + DataToNetwork(buffer, count, control);
456     case JUST_GOT_AID:
457 	Ensure(2);
458 	PrintAddr(Addr3270(buffer[0], buffer[1]));
459 	putSpace();
460 	buffer += 2;
461 	count -= 2;
462 	state = DATA;
463 	return origCount - count + DataToNetwork(buffer, count, control);
464     case DATA:
465     case DATA_CONTINUE:
466 	while (count) {
467 	    if (*buffer == ORDER_SBA) {
468 		if (state == DATA_CONTINUE) {
469 		    Undent();
470 		    state = DATA;
471 		}
472 		putstr("SBA ");
473 		PrintAddr(Addr3270(buffer[1], buffer[2]));
474 		putSpace();
475 		buffer += 3;
476 		count -= 3;
477 	    } else {
478 		if (state == DATA) {
479 		    putstr("DATA:");
480 		    Indent();
481 		    state = DATA_CONTINUE;
482 		}
483 		putEChar(*buffer);
484 		buffer++;
485 		count--;
486 	    }
487 	}
488 	if (control) {
489 	    if (state == DATA_CONTINUE) {
490 		Undent();
491 	    }
492 	    state = NEED_AID;
493 	}
494 	return origCount-count;
495     }
496 }
497 
498 int
499 GetXValue(c)
500 int	c;
501 {
502     if (!isascii(c)) {
503 	fflush(stdout);
504 	fprintf(stderr, "Non-hex digit 0x%x.\n");
505 	fflush(stderr);
506 	return 0;
507     } else {
508 	if (islower(c)) {
509 	    return (c-'a')+10;
510 	} else if (isupper(c)) {
511 	    return (c-'A')+10;
512 	} else {
513 	    return c-'0';
514 	}
515     }
516 }
517 
518 unsigned char outbound[8192], inbound[8192],
519 	*outnext = outbound, *innext = inbound, *p = 0;
520 
521 void
522 termblock(old, new, control)
523 int old,
524 	new;		/* old and new directions */
525 {
526     int count;
527 
528     if (p) {
529 	if (old == '<') {
530 	    outnext = p;
531 	    count = DataFromNetwork(outbound, outnext-outbound, control);
532 	    if (outbound+count == outnext) {
533 		outnext = outbound;
534 	    } else {
535 		memcpy(outbound, outbound+count, outnext-(outbound+count));
536 		outnext = outbound+count;
537 	    }
538 	} else {
539 	    innext = p;
540 	    count = DataToNetwork(inbound, innext-inbound, control);
541 	    if (inbound+count == innext) {
542 		innext = inbound;
543 	    } else {
544 		memcpy(inbound, inbound+count, innext-(inbound+count));
545 		innext = inbound+count;
546 	    }
547 	}
548     }
549     if (new == '<') {
550 	p = outnext;
551     } else if (new == '>') {
552 	p = innext;
553     } else {
554 	fprintf(stderr, "Bad direction character '%c'.\n", new);
555 	exit(1);
556     }
557 }
558 
559 main()
560 {
561     int location;
562     int new;
563     int c, c1;
564 
565     memset(Orders, 0, sizeof Orders);
566     Orders[ORDER_SF] = Orders[ORDER_SBA] = Orders[ORDER_IC]
567 	    = Orders[ORDER_PT] = Orders[ORDER_RA] = Orders[ORDER_EUA]
568 	    = Orders[ORDER_YALE] = 1;
569 
570     while (scanf("%c 0x%x\t", &new, &location) != EOF) {
571 	if (new != direction) {
572 	    termblock(direction, new, 0);
573 	    direction = new;
574 	}
575 	while (((c = getchar()) != EOF) && (c != '\n') && (isxdigit(c))) {
576 #define	NORMAL	0
577 #define	GOT0XFF	0xff
578 	    static int state = NORMAL;
579 
580 	    c1 = getchar();
581 	    c = (GetXValue(c) << 4) + GetXValue(c1);
582 	    switch (state) {
583 	    case NORMAL:
584 		if (c == 0xff) {
585 		    state = GOT0XFF;
586 		} else {
587 		    *p++ = c;
588 		}
589 		break;
590 	    case GOT0XFF:
591 		if (c == 0xef) {
592 		    termblock(direction, direction, 1);
593 		} else {
594 		    *p++ = 0xff;
595 		    *p++ = c;
596 		}
597 		state = NORMAL;
598 	    }
599 	}
600     }
601     return 0;
602 }
603