Annotation of researchv10no/ncurses/screen/tparm.c, revision 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.