Annotation of researchv10no/ncurses/screen/tparm.c, revision 1.1.1.1

1.1       root        1: static  char sccsid[] = "@(#)tparm.c   1.1     (1.9    3/4/83)";
                      2: /* Copyright (c) 1979 Regents of the University of California */
                      3: 
                      4: #include "curses.h"
                      5: #include "term.h"
                      6: 
                      7: #ifdef NONSTANDARD
                      8: #include       "ns_curses.h"
                      9: #endif
                     10: 
                     11: #define        CTRL(c) ('c' & 037)
                     12: /* #define _err(msg) 0 */
                     13: static char *_err();
                     14: char *_branchto();
                     15: 
                     16: /*
                     17:  * Routine to perform parameter substitution.
                     18:  * instring is a string containing printf type escapes.
                     19:  * The whole thing uses a stack, much like an HP 35.
                     20:  * The following escapes are defined for substituting row/column:
                     21:  *
                     22:  *     %d      print pop() as in printf
                     23:  *     %[0]2d  print pop() like %[0]2d
                     24:  *     %[0]3d  print pop() like %[0]3d
                     25:  *     %c      print pop() like %c
                     26:  *     %s      print pop() like %s
                     27:  *     %l      pop() a string and push its length.
                     28:  *
                     29:  *     %p[1-0] push ith parm
                     30:  *     %P[a-z] set variable
                     31:  *     %g[a-z] get variable
                     32:  *     %'c'    char constant c
                     33:  *     %{nn}   integer constant nn
                     34:  *
                     35:  *     %+ %- %* %/ %m          arithmetic (%m is mod): push(pop() op pop())
                     36:  *     %& %| %^                bit operations:         push(pop() op pop())
                     37:  *     %= %> %<                logical operations:     push(pop() op pop())
                     38:  *     %! %~                   unary operations        push(op pop())
                     39:  *     %b                      unary BCD conversion
                     40:  *     %d                      unary Delta Data conversion
                     41:  *
                     42:  *     %? expr %t thenpart %e elsepart %;
                     43:  *                             if-then-else, %e elsepart is optional.
                     44:  *                             else-if's are possible ala Algol 68:
                     45:  *                             %? c1 %t %e c2 %t %e c3 %t %e c4 %t %e %;
                     46:  *
                     47:  * all other characters are ``self-inserting''.  %% gets % output.
                     48:  */
                     49: 
                     50: /* #define tparmdebug */
                     51: #ifdef tparmdebug
                     52: char *tparm();
                     53: #include <stdio.h>
                     54: #define DEBUG
                     55: FILE *outf;
                     56: main()
                     57: {
                     58:        int so, ul, rev, bl, dim, bold, blank, prot, alt;
                     59:        setupterm(getenv("TERM"), 1, 0);
                     60:        outf = stdout;
                     61:        for (;;) {
                     62:                printf("so, ul, rev, bl, dim, bold, blank, prot, alt: ");
                     63:                scanf("%d %d %d %d %d %d %d %d %d",
                     64:                &so, &ul, &rev, &bl, &dim, &bold, &blank, &prot, &alt);
                     65:                printf("-->%s<--\n", tparm(set_attributes,
                     66:                        so, ul, rev, bl, dim, bold, blank, prot, alt));
                     67:        }
                     68: }
                     69: 
                     70: _prstr(result)
                     71: char *result;
                     72: {
                     73:        register char *cp;
                     74: 
                     75:        for (cp=result; *cp; cp++)
                     76:                if (*cp >= ' ' && *cp <= '~')
                     77:                        putchar(*cp);
                     78:                else
                     79:                        printf("\\%o", *cp&0377);
                     80: }
                     81: #endif
                     82: 
                     83: #define push(i) (stack[++top] = (i))
                     84: #define pop()  (stack[top--])
                     85: 
                     86: /* VARARGS */
                     87: char *
                     88: tparm(instring, p1, p2, p3, p4, p5, p6, p7, p8, p9)
                     89:        char *instring;
                     90:        int p1, p2, p3, p4, p5, p6, p7, p8 ,p9;
                     91: {
                     92:        static char result[32];
                     93:        static char added[10];
                     94:        int vars[26];
                     95:        int stack[10], top = 0;
                     96:        register char *cp = instring;
                     97:        register char *outp = result;
                     98:        register int c;
                     99:        register int op;
                    100:        int sign;
                    101:        int onrow = 0;
                    102:        int leadzero = 0;       /* not having leading zero is unimplemented */
                    103:        char *xp;
                    104: 
                    105:        if (instring == 0)
                    106:                return _err("null arg");
                    107:        added[0] = 0;
                    108: #ifdef tparmdebug
                    109:        printf("'");
                    110:        _prstr(instring);
                    111:        printf("'\n");
                    112: #endif
                    113: 
                    114:        while (c = *cp++) {
                    115: #ifdef tparmdebug
                    116: printf("loop, c %c%c%c, top %d @ %d, 2nd %d, out '",
                    117:        c, *cp, *(cp+1), stack[top], top, stack[top-1]);
                    118: _prstr(result); printf("'\n");
                    119: #endif
                    120:                if (c != '%') {
                    121:                        *outp++ = c;
                    122:                        continue;
                    123:                }
                    124:                op = stack[top];
                    125:                if (*cp == '0') {
                    126:                        leadzero = 1;
                    127:                        cp++;
                    128:                }
                    129:                switch (c = *cp++) {
                    130: 
                    131:                /* PRINTING CASES */
                    132:                case 'd':
                    133:                        if (op < 10)
                    134:                                goto one;
                    135:                        if (op < 100)
                    136:                                goto two;
                    137:                        /* fall into... */
                    138: 
                    139:                case '3':
                    140: three:
                    141:                        if (c == '3' && *cp++ != 'd')
                    142:                                return _err("bad char after %3");
                    143:                        *outp++ = (op / 100) | '0';
                    144:                        op %= 100;
                    145:                        /* fall into... */
                    146: 
                    147:                case '2':
                    148:                        if (op >= 100)
                    149:                                goto three;
                    150:                        if (c == '2' && *cp++ != 'd')
                    151:                                return _err("bad char after %2");
                    152: two:   
                    153:                        *outp++ = op / 10 | '0';
                    154: one:
                    155:                        *outp++ = op % 10 | '0';
                    156:                        (void) pop();
                    157:                        continue;
                    158: 
                    159:                case 'c':
                    160:                        /*
                    161:                         * This code is worth scratching your head at for a
                    162:                         * while.  The idea is that various weird things can
                    163:                         * happen to nulls, EOT's, tabs, and newlines by the
                    164:                         * tty driver, arpanet, and so on, so we don't send
                    165:                         * them if we can help it.  So we instead alter the
                    166:                         * place being addessed and then move the cursor
                    167:                         * locally using UP or RIGHT.
                    168:                         *
                    169:                         * This is a kludge, clearly.  It loses if the
                    170:                         * parameterized string isn't addressing the cursor
                    171:                         * (but hopefully that is all that %c terminals do
                    172:                         * with parms).  Also, since tab and newline happen
                    173:                         * to be next to each other in ASCII, if tab were
                    174:                         * included a loop would be needed.  Finally, note
                    175:                         * that lots of other processing is done here, so
                    176:                         * this hack won't always work (e.g. the Ann Arbor
                    177:                         * 4080, which uses %B and then %c.)
                    178:                         */
                    179:                        switch (op) {
                    180:                                /*
                    181:                                 * Null.  Problem is that our output is, by
                    182:                                 * convention, null terminated.
                    183:                                 */
                    184:                        case 0:
                    185:                                op = 0200;   /* Parity should be ignored */
                    186:                                break;
                    187:                                /*
                    188:                                 * Control D.  Problem is that certain very
                    189:                                 * ancient hardware hangs up on this, so the
                    190:                                 * current (!) UNIX tty driver doesn't xmit
                    191:                                 * control D's.
                    192:                                 */
                    193:                        case CTRL(d):
                    194:                                /*
                    195:                                 * Newline.  Problem is that UNIX will expand
                    196:                                 * this to CRLF.
                    197:                                 */
                    198:                        case '\n':
                    199:                                xp = onrow ? cursor_down : cursor_right;
                    200:                                if (onrow && xp && op < lines-1 && cursor_up) {
                    201:                                        op += 2;
                    202:                                        xp = cursor_up;
                    203:                                }
                    204:                                if (xp && instring == cursor_address) {
                    205:                                        strcat(added, xp);
                    206:                                        op--;
                    207:                                }
                    208:                                break;
                    209:                                /*
                    210:                                 * Tab used to be in this group too,
                    211:                                 * because UNIX might expand it to blanks.
                    212:                                 * We now require that this tab mode be turned
                    213:                                 * off by any program using this routine,
                    214:                                 * or using termcap in general, since some
                    215:                                 * terminals use tab for other stuff, like
                    216:                                 * nondestructive space.  (Filters like ul
                    217:                                 * or vcrt will lose, since they can't stty.)
                    218:                                 * Tab was taken out to get the Ann Arbor
                    219:                                 * 4080 to work.
                    220:                                 */
                    221:                        }
                    222: 
                    223:                        *outp++ = op;
                    224:                        (void) pop();
                    225:                        break;
                    226: 
                    227:                case 'l':
                    228:                        xp = (char *) pop();
                    229:                        push(strlen(xp));
                    230:                        break;
                    231: 
                    232:                case 's':
                    233:                        xp = (char *) pop();
                    234:                        while (*xp)
                    235:                                *outp++ = *xp++;
                    236:                        break;
                    237: 
                    238:                case '%':
                    239:                        *outp++ = c;
                    240:                        break;
                    241: 
                    242:                /*
                    243:                 * %i: shorthand for increment first two parms.
                    244:                 * Useful for terminals that start numbering from
                    245:                 * one instead of zero (like ANSI terminals).
                    246:                 */
                    247:                case 'i':
                    248:                        p1++; p2++;
                    249:                        break;
                    250: 
                    251:                /* %pi: push the ith parameter */
                    252:                case 'p':
                    253:                        switch (c = *cp++) {
                    254:                        case '1': push(p1); break;
                    255:                        case '2': push(p2); break;
                    256:                        case '3': push(p3); break;
                    257:                        case '4': push(p4); break;
                    258:                        case '5': push(p5); break;
                    259:                        case '6': push(p6); break;
                    260:                        case '7': push(p7); break;
                    261:                        case '8': push(p8); break;
                    262:                        case '9': push(p9); break;
                    263:                        default: return _err("bad parm number");
                    264:                        }
                    265:                        onrow = (c == '1');
                    266:                        break;
                    267:                
                    268:                /* %Pi: pop from stack into variable i (a-z) */
                    269:                case 'P':
                    270:                        vars[*cp++ - 'a'] = pop();
                    271:                        break;
                    272:                
                    273:                /* %gi: push variable i (a-z) */
                    274:                case 'g':
                    275:                        push(vars[*cp++ - 'a']);
                    276:                        break;
                    277:                
                    278:                /* %'c' : character constant */
                    279:                case '\'':
                    280:                        push(*cp++);
                    281:                        if (*cp++ != '\'')
                    282:                                return _err("missing closing quote");
                    283:                        break;
                    284:                
                    285:                /* %{nn} : integer constant.  */
                    286:                case '{':
                    287:                        op = 0; sign = 1;
                    288:                        if (*cp == '-') {
                    289:                                sign = -1;
                    290:                                cp++;
                    291:                        } else if (*cp == '+')
                    292:                                cp++;
                    293:                        while ((c = *cp++) >= '0' && c <= '9') {
                    294:                                op = 10*op + c - '0';
                    295:                        }
                    296:                        if (c != '}')
                    297:                                return _err("missing closing brace");
                    298:                        push(sign * op);
                    299:                        break;
                    300:                
                    301:                /* binary operators */
                    302:                case '+': c=pop(); op=pop(); push(op + c); break;
                    303:                case '-': c=pop(); op=pop(); push(op - c); break;
                    304:                case '*': c=pop(); op=pop(); push(op * c); break;
                    305:                case '/': c=pop(); op=pop(); push(op / c); break;
                    306:                case 'm': c=pop(); op=pop(); push(op % c); break; /* %m: mod */
                    307:                case '&': c=pop(); op=pop(); push(op & c); break;
                    308:                case '|': c=pop(); op=pop(); push(op | c); break;
                    309:                case '^': c=pop(); op=pop(); push(op ^ c); break;
                    310:                case '=': c=pop(); op=pop(); push(op = c); break;
                    311:                case '>': c=pop(); op=pop(); push(op > c); break;
                    312:                case '<': c=pop(); op=pop(); push(op < c); break;
                    313: 
                    314:                /* Unary operators. */
                    315:                case '!': stack[top] = !stack[top]; break;
                    316:                case '~': stack[top] = ~stack[top]; break;
                    317:                /* Sorry, no unary minus, because minus is binary. */
                    318: 
                    319:                /*
                    320:                 * If-then-else.  Implemented by a low level hack of
                    321:                 * skipping forward until the match is found, counting
                    322:                 * nested if-then-elses.
                    323:                 */
                    324:                case '?':       /* IF - just a marker */
                    325:                        break;
                    326: 
                    327:                case 't':       /* THEN - branch if false */
                    328:                        if (!pop())
                    329:                                cp = _branchto(cp, 'e');
                    330:                        break;
                    331: 
                    332:                case 'e':       /* ELSE - branch to ENDIF */
                    333:                        cp = _branchto(cp, ';');
                    334:                        break;
                    335: 
                    336:                case ';':       /* ENDIF - just a marker */
                    337:                        break;
                    338: 
                    339:                default:
                    340:                        return _err("bad % sequence");
                    341:                }
                    342:        }
                    343: #ifdef tparmdebug
                    344: printf("part a: '");
                    345: _prstr(result);
                    346: printf("', len %d, part b: '", outp-result);
                    347: _prstr(added);
                    348: printf("'\n");
                    349: #endif
                    350:        strcpy(outp, added);
                    351:        return (result);
                    352: }
                    353: 
                    354: static
                    355: char *
                    356: _err(msg)
                    357: char *msg;
                    358: {
                    359: #ifdef tparmdebug
                    360:        write(2,"tparm: ", 7);
                    361:        write(2, msg, strlen(msg));
                    362:        write(2, "\r\n", 2);
                    363: #endif
                    364:        return 0;
                    365: }
                    366: 
                    367: char *
                    368: _branchto(cp, to)
                    369: register char *cp;
                    370: char to;
                    371: {
                    372:        register int level = 0;
                    373:        register char c;
                    374: 
                    375:        while (c = *cp++) {
                    376:                if (c == '%') {
                    377:                        if ((c = *cp++) == to || c == ';') {
                    378:                                if (level == 0) {
                    379:                                        return cp;
                    380:                                }
                    381:                        }
                    382:                        if (c == '?')
                    383:                                level++;
                    384:                        if (c == ';')
                    385:                                level--;
                    386:                }
                    387:        }
                    388:        return _err("no matching ENDIF");
                    389: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.