|
|
1.1 root 1: /*********************************************************************
2: * COPYRIGHT NOTICE *
3: **********************************************************************
4: * This software is copyright (C) 1982 by Pavel Curtis *
5: * *
6: * Permission is granted to reproduce and distribute *
7: * this file by any means so long as no fee is charged *
8: * above a nominal handling fee and so long as this *
9: * notice is always included in the copies. *
10: * *
11: * Other rights are reserved except as explicitly granted *
12: * by written permission of the author. *
13: * Pavel Curtis *
14: * Computer Science Dept. *
15: * 405 Upson Hall *
16: * Cornell University *
17: * Ithaca, NY 14853 *
18: * *
19: * Ph- (607) 256-4934 *
20: * *
21: * Pavel.Cornell@Udel-Relay (ARPAnet) *
22: * decvax!cornell!pavel (UUCPnet) *
23: *********************************************************************/
24:
25: /*
26: * tparm.c
27: *
28: * $Log: lib_tparm.c,v $
29: * Revision 1.8 93/04/12 14:14:30 bin
30: * Udo: third color update
31: *
32: * Revision 2.4 92/10/23 00:31:38 munk
33: * npush(npop()...) does not work with COHERENT's cc
34: * because of side effects, use x = npop(); npush(x...) instead.
35: * Now hold x and y in register, not level.
36: *
37: * Revision 1.2 92/04/13 14:38:35 bin
38: * update by vlad
39: *
40: * Revision 2.2 91/04/20 21:54:27 munk
41: * Usage of register variables
42: *
43: * Revision 2.1 82/10/25 14:49:19 pavel
44: * Added Copyright Notice
45: *
46: * Revision 2.0 82/10/24 15:17:53 pavel
47: * Beta-one Test Release
48: *
49: * Revision 1.3 82/08/23 22:30:38 pavel
50: * The REAL Alpha-one Release Version
51: *
52: * Revision 1.2 82/08/19 19:11:33 pavel
53: * Alpha Test Release One
54: *
55: * Revision 1.1 82/08/12 18:45:33 pavel
56: * Initial revision
57: *
58: *
59: */
60:
61: #ifdef RCSHDR
62: static char RCSid[] =
63: "$Header: /src386/usr/lib/ncurses/RCS/lib_tparm.c,v 1.8 93/04/12 14:14:30 bin Exp Locker: bin $";
64: #endif
65:
66: #include "curses.h"
67: #include "curses.priv.h"
68: #include "term.h"
69:
70:
71: /*
72: * char *
73: * tparm(string, parms)
74: *
75: * Substitute the given parameters into the given string by the following
76: * rules (taken from terminfo(5)):
77: *
78: * Cursor addressing and other strings requiring parame-
79: * ters in the terminal are described by a parameterized string
80: * capability, with like escapes %x in it. For example, to
81: * address the cursor, the cup capability is given, using two
82: * parameters: the row and column to address to. (Rows and
83: * columns are numbered from zero and refer to the physical
84: * screen visible to the user, not to any unseen memory.) If
85: * the terminal has memory relative cursor addressing, that can
86: * be indicated by
87: *
88: * The parameter mechanism uses a stack and special %
89: * codes to manipulate it. Typically a sequence will push one
90: * of the parameters onto the stack and then print it in some
91: * format. Often more complex operations are necessary.
92: *
93: * The % encodings have the following meanings:
94: *
95: * %% outputs `%'
96: * %d print pop() like %d in printf()
97: * %2d print pop() like %2d in printf()
98: * %02d print pop() like %02d in printf()
99: * %3d print pop() like %3d in printf()
100: * %03d print pop() like %03d in printf()
101: * %c print pop() like %c in printf()
102: * %s print pop() like %s in printf()
103: *
104: * %p[1-9] push ith parm
105: * %P[a-z] set variable [a-z] to pop()
106: * %g[a-z] get variable [a-z] and push it
107: * %'c' push char constant c
108: * %{nn} push integer constant nn
109: *
110: * %+ %- %* %/ %m
111: * arithmetic (%m is mod): push(pop() op pop())
112: * %& %| %^ bit operations: push(pop() op pop())
113: * %= %> %< logical operations: push(pop() op pop())
114: * %! %~ unary operations push(op pop())
115: * %i add 1 to first two parms (for ANSI terminals)
116: *
117: * %? expr %t thenpart %e elsepart %;
118: * if-then-else, %e elsepart is optional.
119: * else-if's are possible ala Algol 68:
120: * %? c1 %t b1 %e c2 %t b2 %e c3 %t b3 %e c4 %t b4 %e b5 %;
121: *
122: * For those of the above operators which are binary and not commutative,
123: * the stack works in the usual way, with
124: * %gx %gy %m
125: * resulting in x mod y, not the reverse.
126: */
127:
128: #define STACKSIZE 20
129:
130: #define npush(x) if (stack_ptr < STACKSIZE) {stack[stack_ptr].num = x;\
131: stack_ptr++;\
132: }
133: #define npop() (stack_ptr > 0 ? stack[--stack_ptr].num : 0)
134: #define spop() (stack_ptr > 0 ? stack[--stack_ptr].str : (char *) 0)
135:
136: typedef union
137: {
138: unsigned int num;
139: char *str;
140: } stack_frame;
141:
142: stack_frame stack[STACKSIZE];
143: static int stack_ptr;
144: static char buffer[256];
145: static int *param;
146: static char *bufptr;
147: static int variable[26];
148:
149: static char *do_tparm();
150:
151:
152: char *
153: tparm(string, parms)
154: register char *string;
155: int parms;
156: {
157: char *strcpy();
158: char len;
159: int number;
160: int level;
161: register int x, y;
162:
163: param = &parms;
164:
165: #ifdef TRACE
166: if (_tracing)
167: _tracef("tparm(%s,%d,%d,%d,%d,%d,%d,%d,%d,%d) called",
168: string, param[0], param[1], param[2], param[3],
169: param[4], param[5], param[6], param[7], param[8]);
170: #endif
171:
172: stack_ptr = 0;
173: bufptr = buffer;
174:
175: while (*string)
176: {
177: if (*string != '%')
178: *(bufptr++) = *string;
179: else
180: {
181: string++;
182: switch (*string)
183: {
184: default:
185: break;
186:
187: case '%':
188: *(bufptr++) = '%';
189: break;
190:
191: case 'd':
192: sprintf(bufptr, "%d", npop());
193: bufptr += strlen(bufptr);
194: break;
195:
196: case '0':
197: string++;
198: len = *string;
199: if ((len == '2' || len == '3') && *++string == 'd')
200: {
201: if (len == '2')
202: sprintf(bufptr, "%02d", npop());
203: else
204: sprintf(bufptr, "%03d", npop());
205:
206: bufptr += strlen(bufptr);
207: }
208: break;
209:
210: case '2':
211: string++;
212: if (*string == 'd')
213: {
214: sprintf(bufptr, "%2d", npop());
215: bufptr += strlen(bufptr);
216: }
217: break;
218:
219: case '3':
220: string++;
221: if (*string == 'd')
222: {
223: sprintf(bufptr, "%3d", npop());
224: bufptr += strlen(bufptr);
225: }
226: break;
227:
228: case 'c':
229: *(bufptr++) = (char) npop();
230: break;
231:
232: case 's':
233: strcpy(bufptr, spop());
234: bufptr += strlen(bufptr);
235: break;
236:
237: case 'p':
238: string++;
239: if (*string >= '1' && *string <= '9')
240: npush(param[*string - '1']);
241: break;
242:
243: case 'P':
244: string++;
245: if (*string >= 'a' && *string <= 'z')
246: variable[*string - 'a'] = npop();
247: break;
248:
249: case 'g':
250: string++;
251: if (*string >= 'a' && *string <= 'z')
252: npush(variable[*string - 'a']);
253: break;
254:
255: case '\'':
256: string++;
257: npush(*string);
258: string++;
259: break;
260:
261: case '{':
262: number = 0;
263: string++;
264: while (*string >= '0' && *string <= '9')
265: {
266: number = number * 10 + *string - '0';
267: string++;
268: }
269: npush(number);
270: break;
271:
272: case '+':
273: y = npop();
274: x = npop();
275: npush(x + y);
276: break;
277:
278: case '-':
279: y = npop();
280: x = npop();
281: npush(x - y);
282: break;
283:
284: case '*':
285: y = npop();
286: x = npop();
287: npush(x * y);
288: break;
289:
290: case '/':
291: y = npop();
292: x = npop();
293: npush(x / y);
294: break;
295:
296: case 'm':
297: y = npop();
298: x = npop();
299: npush(x % y);
300: break;
301:
302: case '&':
303: y = npop();
304: x = npop();
305: npush(x & y);
306: break;
307:
308: case '|':
309: y = npop();
310: x = npop();
311: npush(x | y);
312: break;
313:
314: case '^':
315: y = npop();
316: x = npop();
317: npush(x ^ y);
318: break;
319:
320: case '=':
321: y = npop();
322: x = npop();
323: npush(x == y);
324: break;
325:
326: case '<':
327: y = npop();
328: x = npop();
329: npush(x < y);
330: break;
331:
332: case '>':
333: y = npop();
334: x = npop();
335: npush(x > y);
336: break;
337:
338: case '!':
339: x = ! npop();
340: npush(x);
341: break;
342:
343: case '~':
344: x = ~ npop();
345: npush(x);
346: break;
347:
348: case 'i':
349: param[0]++;
350: param[1]++;
351: break;
352:
353: case '?':
354: break;
355:
356: case 't':
357: x = npop();
358: if (x)
359: {
360: /* do nothing; keep executing */
361: }
362: else
363: {
364: /* scan forward for %e or %; at level zero */
365: string++;
366: level = 0;
367: while (*string)
368: {
369: if (*string == '%')
370: {
371: string++;
372: if (*string == '?')
373: level++;
374: else if (*string == ';')
375: {
376: if (level > 0)
377: level--;
378: else
379: break;
380: }
381: else if (*string == 'e' && level == 0)
382: break;
383: }
384:
385: if (*string)
386: string++;
387: }
388: }
389: break;
390:
391: case 'e':
392: /* scan forward for a %; at level zero */
393: string++;
394: level = 0;
395: while (*string)
396: {
397: if (*string == '%')
398: {
399: string++;
400: if (*string == '?')
401: level++;
402: else if (*string == ';')
403: {
404: if (level > 0)
405: level--;
406: else
407: break;
408: }
409: }
410:
411: if (*string)
412: string++;
413: }
414: break;
415:
416: case ';':
417: break;
418:
419: } /* endswitch (*string) */
420: } /* endelse (*string == '%') */
421:
422: if (*string == '\0')
423: break;
424:
425: string++;
426: } /* endwhile (*string) */
427:
428: *bufptr = '\0';
429: return(buffer);
430: }
431:
432:
433: /*
434: * char *
435: * tgoto(string, x, y)
436: *
437: * Retained solely for upward compatibility. Note the intentional
438: * reversing of the last two arguments.
439: *
440: */
441:
442: char *
443: tgoto(string, x, y)
444: char *string;
445: int x, y;
446: {
447: return(tparm(string, y, x));
448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.