Annotation of lucent/sys/src/9/port/print.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "../port/lib.h"
                      3: 
                      4: enum
                      5: {
                      6:        SIZE    = 1024,
                      7:        IDIGIT  = 30,
                      8:        MAXCONV = 40,
                      9:        FDIGIT  = 30,
                     10:        FDEFLT  = 6,
                     11:        NONE    = -1000,
                     12:        MAXFMT  = 512,
                     13: 
                     14:        FPLUS   = (1<<0),
                     15:        FMINUS  = (1<<1),
                     16:        FSHARP  = (1<<2),
                     17:        FLONG   = (1<<3),
                     18:        FSHORT  = (1<<4),
                     19:        FUNSIGN = (1<<5),
                     20:        FVLONG  = (1<<6),
                     21: };
                     22: 
                     23: #define        PTR     sizeof(char*)
                     24: #define        SHORT   sizeof(int)
                     25: #define        INT     sizeof(int)
                     26: #define        LONG    sizeof(long)
                     27: #define        VLONG   sizeof(vlong)
                     28: 
                     29: int    printcol;
                     30: 
                     31: static int     convcount;
                     32: static char    fmtindex[MAXFMT];
                     33: 
                     34: static int     noconv(void*, Fconv*);
                     35: static int     flags(void*, Fconv*);
                     36: 
                     37: static int     cconv(void*, Fconv*);
                     38: static int     sconv(void*, Fconv*);
                     39: static int     percent(void*, Fconv*);
                     40: 
                     41: int    numbconv(void*, Fconv*);
                     42: 
                     43: static
                     44: int    (*fmtconv[MAXCONV])(void*, Fconv*) =
                     45: {
                     46:        noconv
                     47: };
                     48: 
                     49: static
                     50: void
                     51: initfmt(void)
                     52: {
                     53:        int cc;
                     54: 
                     55:        cc = 0;
                     56:        fmtconv[cc] = noconv;
                     57:        cc++;
                     58: 
                     59:        fmtconv[cc] = flags;
                     60:        fmtindex['+'] = cc;
                     61:        fmtindex['-'] = cc;
                     62:        fmtindex['#'] = cc;
                     63:        fmtindex['h'] = cc;
                     64:        fmtindex['l'] = cc;
                     65:        fmtindex['u'] = cc;
                     66:        cc++;
                     67: 
                     68:        fmtconv[cc] = numbconv;
                     69:        fmtindex['d'] = cc;
                     70:        fmtindex['o'] = cc;
                     71:        fmtindex['x'] = cc;
                     72:        fmtindex['X'] = cc;
                     73:        cc++;
                     74: 
                     75:        fmtconv[cc] = cconv;
                     76:        fmtindex['c'] = cc;
                     77:        fmtindex['C'] = cc;
                     78:        cc++;
                     79: 
                     80:        fmtconv[cc] = sconv;
                     81:        fmtindex['s'] = cc;
                     82:        fmtindex['S'] = cc;
                     83:        cc++;
                     84: 
                     85:        fmtconv[cc] = percent;
                     86:        fmtindex['%'] = cc;
                     87:        cc++;
                     88: 
                     89:        convcount = cc;
                     90: }
                     91: 
                     92: int
                     93: fmtinstall(int c, int (*f)(void*, Fconv*))
                     94: {
                     95: 
                     96:        if(convcount == 0)
                     97:                initfmt();
                     98:        if(c < 0 || c >= MAXFMT)
                     99:                return 1;
                    100:        if(convcount >= MAXCONV)
                    101:                return 1;
                    102:        fmtconv[convcount] = f;
                    103:        fmtindex[c] = convcount;
                    104:        convcount++;
                    105:        return 0;
                    106: }
                    107: 
                    108: char*
                    109: doprint(char *s, char *es, char *fmt, void *argp)
                    110: {
                    111:        int n, c;
                    112:        Rune rune;
                    113:        Fconv local;
                    114: 
                    115:        local.out = s;
                    116:        local.eout = es-4;              /* room for multi-byte character and 0 */
                    117: 
                    118: loop:
                    119:        c = *fmt & 0xff;
                    120:        if(c >= Runeself) {
                    121:                n = chartorune(&rune, fmt);
                    122:                fmt += n;
                    123:                c = rune;
                    124:        } else
                    125:                fmt++;
                    126:        switch(c) {
                    127:        case 0:
                    128:                *local.out = 0;
                    129:                return local.out;
                    130:        
                    131:        default:
                    132:                printcol++;
                    133:                goto common;
                    134: 
                    135:        case '\n':
                    136:                printcol = 0;
                    137:                goto common;
                    138: 
                    139:        case '\t':
                    140:                printcol = (printcol+8) & ~7;
                    141:                goto common;
                    142: 
                    143:        common:
                    144:                if(local.out < local.eout)
                    145:                        if(c >= Runeself) {
                    146:                                rune = c;
                    147:                                n = runetochar(local.out, &rune);       /* BUG */
                    148:                                local.out += n;
                    149:                        } else
                    150:                                *local.out++ = c;
                    151:                goto loop;
                    152: 
                    153:        case '%':
                    154:                break;
                    155:        }
                    156:        local.f1 = NONE;
                    157:        local.f2 = NONE;
                    158:        local.f3 = 0;
                    159: 
                    160:        /*
                    161:         * read one of the following
                    162:         *      1. number, => f1, f2 in order.
                    163:         *      2. '*' same as number (from args)
                    164:         *      3. '.' ignored (separates numbers)
                    165:         *      4. flag => f3
                    166:         *      5. verb and terminate
                    167:         */
                    168: l0:
                    169:        c = *fmt & 0xff;
                    170:        if(c >= Runeself) {
                    171:                n = chartorune(&rune, fmt);
                    172:                fmt += n;
                    173:                c = rune;
                    174:        } else
                    175:                fmt++;
                    176: 
                    177: l1:
                    178:        if(c == 0) {
                    179:                fmt--;
                    180:                goto loop;
                    181:        }
                    182:        if(c == '.') {
                    183:                if(local.f1 == NONE)
                    184:                        local.f1 = 0;
                    185:                local.f2 = 0;
                    186:                goto l0;
                    187:        }
                    188:        if((c >= '1' && c <= '9') ||
                    189:           (c == '0' && local.f1 != NONE)) {    /* '0' is a digit for f2 */
                    190:                n = 0;
                    191:                while(c >= '0' && c <= '9') {
                    192:                        n = n*10 + c-'0';
                    193:                        c = *fmt++;
                    194:                }
                    195:                if(local.f1 == NONE)
                    196:                        local.f1 = n;
                    197:                else
                    198:                        local.f2 = n;
                    199:                goto l1;
                    200:        }
                    201:        if(c == '*') {
                    202:                n = *(int*)argp;
                    203:                argp = (char*)argp + INT;
                    204:                if(local.f1 == NONE)
                    205:                        local.f1 = n;
                    206:                else
                    207:                        local.f2 = n;
                    208:                goto l0;
                    209:        }
                    210:        n = 0;
                    211:        if(c >= 0 && c < MAXFMT)
                    212:                n = fmtindex[c];
                    213:        local.chr = c;
                    214:        n = (*fmtconv[n])(argp, &local);
                    215:        if(n < 0) {
                    216:                local.f3 |= -n;
                    217:                goto l0;
                    218:        }
                    219:        argp = (char*)argp + n;
                    220:        goto loop;
                    221: }
                    222: 
                    223: int
                    224: numbconv(void *o, Fconv *fp)
                    225: {
                    226:        char s[IDIGIT];
                    227:        int i, f, n, r, b, ucase;
                    228:        short h;
                    229:        long v;
                    230:        vlong vl;
                    231: 
                    232:        SET(v);
                    233:        SET(vl);
                    234: 
                    235:        ucase = 0;
                    236:        b = fp->chr;
                    237:        switch(fp->chr) {
                    238:        case 'u':
                    239:                fp->f3 |= FUNSIGN;
                    240:        case 'd':
                    241:                b = 10;
                    242:                break;
                    243: 
                    244:        case 'o':
                    245:                b = 8;
                    246:                break;
                    247: 
                    248:        case 'X':
                    249:                ucase = 1;
                    250:        case 'x':
                    251:                b = 16;
                    252:                break;
                    253:        }
                    254: 
                    255:        f = 0;
                    256:        switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
                    257:        case FVLONG|FLONG:
                    258:                vl = *(vlong*)o;
                    259:                r = VLONG;
                    260:                break;
                    261: 
                    262:        case FLONG:
                    263:                v = *(long*)o;
                    264:                r = LONG;
                    265:                break;
                    266: 
                    267:        case FUNSIGN|FLONG:
                    268:                v = *(ulong*)o;
                    269:                r = LONG;
                    270:                break;
                    271: 
                    272:        case FSHORT:
                    273:                h = *(int*)o;
                    274:                v = h;
                    275:                r = SHORT;
                    276:                break;
                    277: 
                    278:        case FUNSIGN|FSHORT:
                    279:                h = *(int*)o;
                    280:                v = (ushort)h;
                    281:                r = SHORT;
                    282:                break;
                    283: 
                    284:        default:
                    285:                v = *(int*)o;
                    286:                r = INT;
                    287:                break;
                    288: 
                    289:        case FUNSIGN:
                    290:                v = *(unsigned*)o;
                    291:                r = INT;
                    292:                break;
                    293:        }
                    294:        if(!(fp->f3 & FUNSIGN) && v < 0) {
                    295:                v = -v;
                    296:                f = 1;
                    297:        }
                    298:        s[IDIGIT-1] = 0;
                    299:        for(i = IDIGIT-2;; i--) {
                    300:                if(fp->f3 & FVLONG)
                    301:                        n = vl % b;
                    302:                else
                    303:                        n = (ulong)v % b;
                    304:                n += '0';
                    305:                if(n > '9') {
                    306:                        n += 'a' - ('9'+1);
                    307:                        if(ucase)
                    308:                                n += 'A'-'a';
                    309:                }
                    310:                s[i] = n;
                    311:                if(i < 2)
                    312:                        break;
                    313:                if(fp->f3 & FVLONG)
                    314:                        vl = vl / b;
                    315:                else
                    316:                        v = (ulong)v / b;
                    317:                if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
                    318:                        continue;
                    319:                if(fp->f3 & FVLONG)
                    320:                        if(vl <= 0)
                    321:                                break;
                    322:                if(v <= 0)
                    323:                        break;
                    324:        }
                    325:        if(fp->f3 & FSHARP)
                    326:        if(s[i] != '0') {
                    327:                if(b == 8)
                    328:                        s[--i] = '0';
                    329:                else
                    330:                if(b == 16) {
                    331:                        if(ucase)
                    332:                                s[--i] = 'X';
                    333:                        else
                    334:                                s[--i] = 'x';
                    335:                        s[--i] = '0';
                    336:                }
                    337:        }
                    338:        if(f)
                    339:                s[--i] = '-';
                    340:        fp->f2 = NONE;
                    341:        strconv(s+i, fp);
                    342:        return r;
                    343: }
                    344: 
                    345: void
                    346: Strconv(Rune *s, Fconv *fp)
                    347: {
                    348:        int n, c, i;
                    349:        Rune rune;
                    350: 
                    351:        if(fp->f3 & FMINUS)
                    352:                fp->f1 = -fp->f1;
                    353:        n = 0;
                    354:        if(fp->f1 != NONE && fp->f1 >= 0) {
                    355:                for(; s[n]; n++)
                    356:                        ;
                    357:                while(n < fp->f1) {
                    358:                        if(fp->out < fp->eout)
                    359:                                *fp->out++ = ' ';
                    360:                        printcol++;
                    361:                        n++;
                    362:                }
                    363:        }
                    364:        for(;;) {
                    365:                c = *s++;
                    366:                if(c == 0)
                    367:                        break;
                    368:                n++;
                    369:                if(fp->f2 == NONE || fp->f2 > 0) {
                    370:                        if(fp->out < fp->eout)
                    371:                                if(c >= Runeself) {
                    372:                                        rune = c;
                    373:                                        i = runetochar(fp->out, &rune);
                    374:                                        fp->out += i;
                    375:                                } else
                    376:                                        *fp->out++ = c;
                    377:                        if(fp->f2 != NONE)
                    378:                                fp->f2--;
                    379:                        switch(c) {
                    380:                        default:
                    381:                                printcol++;
                    382:                                break;
                    383:                        case '\n':
                    384:                                printcol = 0;
                    385:                                break;
                    386:                        case '\t':
                    387:                                printcol = (printcol+8) & ~7;
                    388:                                break;
                    389:                        }
                    390:                }
                    391:        }
                    392:        if(fp->f1 != NONE && fp->f1 < 0) {
                    393:                fp->f1 = -fp->f1;
                    394:                while(n < fp->f1) {
                    395:                        if(fp->out < fp->eout)
                    396:                                *fp->out++ = ' ';
                    397:                        printcol++;
                    398:                        n++;
                    399:                }
                    400:        }
                    401: }
                    402: 
                    403: void
                    404: strconv(char *s, Fconv *fp)
                    405: {
                    406:        int n, c, i;
                    407:        Rune rune;
                    408: 
                    409:        if(fp->f3 & FMINUS)
                    410:                fp->f1 = -fp->f1;
                    411:        n = 0;
                    412:        if(fp->f1 != NONE && fp->f1 >= 0) {
                    413:                n = utflen(s);
                    414:                while(n < fp->f1) {
                    415:                        if(fp->out < fp->eout)
                    416:                                *fp->out++ = ' ';
                    417:                        printcol++;
                    418:                        n++;
                    419:                }
                    420:        }
                    421:        for(;;) {
                    422:                c = *s & 0xff;
                    423:                if(c >= Runeself) {
                    424:                        i = chartorune(&rune, s);
                    425:                        s += i;
                    426:                        c = rune;
                    427:                } else
                    428:                        s++;
                    429:                if(c == 0)
                    430:                        break;
                    431:                n++;
                    432:                if(fp->f2 == NONE || fp->f2 > 0) {
                    433:                        if(fp->out < fp->eout)
                    434:                                if(c >= Runeself) {
                    435:                                        rune = c;
                    436:                                        i = runetochar(fp->out, &rune);
                    437:                                        fp->out += i;
                    438:                                } else
                    439:                                        *fp->out++ = c;
                    440:                        if(fp->f2 != NONE)
                    441:                                fp->f2--;
                    442:                        switch(c) {
                    443:                        default:
                    444:                                printcol++;
                    445:                                break;
                    446:                        case '\n':
                    447:                                printcol = 0;
                    448:                                break;
                    449:                        case '\t':
                    450:                                printcol = (printcol+8) & ~7;
                    451:                                break;
                    452:                        }
                    453:                }
                    454:        }
                    455:        if(fp->f1 != NONE && fp->f1 < 0) {
                    456:                fp->f1 = -fp->f1;
                    457:                while(n < fp->f1) {
                    458:                        if(fp->out < fp->eout)
                    459:                                *fp->out++ = ' ';
                    460:                        printcol++;
                    461:                        n++;
                    462:                }
                    463:        }
                    464: }
                    465: 
                    466: static
                    467: int
                    468: noconv(void *o, Fconv *fp)
                    469: {
                    470:        int n;
                    471:        char s[10];
                    472: 
                    473:        if(convcount == 0) {
                    474:                initfmt();
                    475:                n = 0;
                    476:                if(fp->chr >= 0 && fp->chr < MAXFMT)
                    477:                        n = fmtindex[fp->chr];
                    478:                return (*fmtconv[n])(o, fp);
                    479:        }
                    480:        sprint(s, "*%c*", fp->chr);
                    481:        fp->f1 = 0;
                    482:        fp->f2 = NONE;
                    483:        fp->f3 = 0;
                    484:        strconv(s, fp);
                    485:        return 0;
                    486: }
                    487: 
                    488: static
                    489: int
                    490: cconv(void *o, Fconv *fp)
                    491: {
                    492:        char s[10];
                    493:        Rune rune;
                    494: 
                    495:        rune = *(int*)o;
                    496:        if(fp->chr == 'c')
                    497:                rune &= 0xff;
                    498:        s[runetochar(s, &rune)] = 0;
                    499: 
                    500:        fp->f2 = NONE;
                    501:        strconv(s, fp);
                    502:        return INT;
                    503: }
                    504: 
                    505: static
                    506: int
                    507: sconv(void *o, Fconv *fp)
                    508: {
                    509:        char *s;
                    510:        Rune *r;
                    511: 
                    512:        if(fp->chr == 's') {
                    513:                s = *(char**)o;
                    514:                if(s == 0)
                    515:                        s = "<null>";
                    516:                strconv(s, fp);
                    517:        } else {
                    518:                r = *(Rune**)o;
                    519:                if(r == 0)
                    520:                        r = L"<null>";
                    521:                Strconv(r, fp);
                    522:        }
                    523:        return PTR;
                    524: }
                    525: 
                    526: static
                    527: int
                    528: percent(void *o, Fconv *fp)
                    529: {
                    530: 
                    531:        USED(o);
                    532:        if(fp->out < fp->eout)
                    533:                *fp->out++ = '%';
                    534:        return 0;
                    535: }
                    536: 
                    537: static
                    538: int
                    539: flags(void *o, Fconv *fp)
                    540: {
                    541:        int f;
                    542: 
                    543:        USED(o);
                    544: 
                    545:        f = 0;
                    546:        switch(fp->chr) {
                    547:        case '+':
                    548:                f = FPLUS;
                    549:                break;
                    550: 
                    551:        case '-':
                    552:                f = FMINUS;
                    553:                break;
                    554: 
                    555:        case '#':
                    556:                f = FSHARP;
                    557:                break;
                    558: 
                    559:        case 'h':
                    560:                f = FSHORT;
                    561:                break;
                    562: 
                    563:        case 'l':
                    564:                f = FLONG;
                    565:                if(fp->f3 & FLONG)
                    566:                        f = FVLONG;
                    567:                break;
                    568: 
                    569:        case 'u':
                    570:                f = FUNSIGN;
                    571:                break;
                    572:        }
                    573:        return -f;
                    574: }

unix.superglobalmegacorp.com

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