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