Annotation of lucent/sys/src/9/port/print.c, revision 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.