Annotation of coherent/d/bin/nroff/getf.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * getf.c
        !             3:  * Nroff/Troff.
        !             4:  * Input handling.
        !             5:  */
        !             6: 
        !             7: #include <ctype.h>
        !             8: #include "roff.h"
        !             9: 
        !            10: #define        ok_name(name) ((name[0]>0 && name[0]<128) && (name[1]>=0 && name[1]<128))
        !            11: 
        !            12: /*
        !            13:  * Get a character handling escapes.
        !            14:  * Flag bit 0: 0 means die if EOF seen, 1 means return EOF.
        !            15:  * Flag bit 1: 2 means copy mode.
        !            16:  * If character is escaped but not recognized as a special escape sequence,
        !            17:  * set escflag and return character unchanged.
        !            18:  */
        !            19: getf(flags) int flags;
        !            20: {
        !            21:        register REG *rp;
        !            22:        register int c, n;
        !            23:        SPECIAL *sp;
        !            24:        char charbuf[CBFSIZE], name[2];
        !            25: 
        !            26:        escflag = 0;
        !            27:        for (;;) {
        !            28:                if ((c = getl(flags&1)) == esc) {
        !            29:                        if ((c = getl(flags&1)) == EOF)
        !            30:                                return c;
        !            31:                        if (c >= ASCSIZE || esctab[c] == ENUL) {
        !            32:                                escflag = 1;
        !            33:                                return c;
        !            34:                        }
        !            35:                        c = esctab[c] & 0377;
        !            36:                }
        !            37:                switch (c) {
        !            38:                case EIGN:
        !            39:                        continue;
        !            40:                case ECOM:
        !            41:                        while ((c=getl(0)) != '\n')
        !            42:                                ;
        !            43:                        return c;
        !            44:                case EARG:
        !            45:                        c = getf(0);
        !            46:                        if (!isdigit(c)) {
        !            47:                                printe("bad argument reference");
        !            48:                                break;
        !            49:                        }
        !            50:                        if (strp->x1.s_argp[c-='0'])
        !            51:                                adscore(strp->x1.s_argp[c]);
        !            52:                        continue;
        !            53:                case ESTR:
        !            54:                        if ((c=getf(0)) != '(') {
        !            55:                                name[0] = c;
        !            56:                                name[1] = '\0';
        !            57:                        } else {
        !            58:                                name[0] = getf(0);
        !            59:                                name[1] = getf(0);
        !            60:                        }
        !            61:                        if (!ok_name(name)) {
        !            62:                                printe("illegal string name");
        !            63:                                break;
        !            64:                        } else if ((rp=findreg(name, RTEXT)))
        !            65:                                adstreg(rp);
        !            66:                        continue;
        !            67:                case ECHR:
        !            68:                        name[0] = getf(0);
        !            69:                        name[1] = getf(0);
        !            70:                        if (!ok_name(name)) {
        !            71:                                printe("illegal special character name");
        !            72:                                break;
        !            73:                        } else if ((sp = spc_find(name)) != NULL)
        !            74:                                adscore(sp->spc_val);
        !            75:                        continue;
        !            76:                case ENUM:
        !            77:                        n = 0;
        !            78:                        if ((c=getf(0)) == '+') {
        !            79:                                n = 1;
        !            80:                                c = getf(0);
        !            81:                        } else if (c == '-') {
        !            82:                                n = -1;
        !            83:                                c = getf(0);
        !            84:                        }
        !            85:                        if (c != '(') {
        !            86:                                name[0] = c;
        !            87:                                name[1] = '\0';
        !            88:                        } else {
        !            89:                                name[0] = getf(0);
        !            90:                                name[1] = getf(0);
        !            91:                        }
        !            92:                        if (!ok_name(name)) {
        !            93:                                printe("illegal register name");
        !            94:                                break;
        !            95:                        } else if ((rp=findreg(name, RNUMR)) == NULL)
        !            96:                                spcnreg(name);
        !            97:                        else {
        !            98:                                rp->n_reg.r_nval += n*rp->n_reg.r_incr;
        !            99:                                adsnval(rp->n_reg.r_nval, rp->n_reg.r_form);
        !           100:                        }
        !           101:                        continue;
        !           102:                case EWID:
        !           103:                        if (flags&2)            /* Copy mode */
        !           104:                                return c;
        !           105:                        if (scandel(charbuf, CBFSIZE) == 0)
        !           106:                                adsnval(0, '1');
        !           107:                        else
        !           108:                                adsnval(getwidth(charbuf), '1');
        !           109:                        continue;
        !           110:                case EBEG:
        !           111:                        if (flags&2)
        !           112:                                return c;
        !           113:                        ++bracelevel;
        !           114:                        return c;
        !           115:                case EEND:
        !           116:                        if (flags&2)
        !           117:                                return c;
        !           118:                        if (bracelevel == 0)
        !           119:                                printe("\\} without matching \\{");
        !           120:                        else
        !           121:                                --bracelevel;
        !           122:                        return c;
        !           123:                case EHEX:
        !           124:                        n = hexdigit(getf(0)) * 0x10;
        !           125:                        n += hexdigit(getf(0));
        !           126:                        return n;
        !           127:                default:
        !           128:                        return c;
        !           129:                }
        !           130:        }
        !           131: }
        !           132: 
        !           133: /*
        !           134:  * Get width of string by processing into temporary environment.
        !           135:  */
        !           136: int
        !           137: getwidth(cp) char *cp;
        !           138: {
        !           139:        int n;
        !           140: 
        !           141:        envsave(ENVWIDTH);
        !           142:        setline();
        !           143:        ccc = ind = tif = fill = 0;
        !           144:        adscore(cp);
        !           145:        strp->x1.s_eoff = 1;
        !           146:        process();
        !           147:        wordbreak(DNULL);
        !           148:        n = nlinsiz;
        !           149:        envload(ENVWIDTH);
        !           150:        return n;
        !           151: }
        !           152: 
        !           153: /*
        !           154:  * Like scandel(), except the delimiter is optional.
        !           155:  * Accepts digits with optional sign without delimiter.
        !           156:  * Currently called only for pointsize changes, e.g. "\s10" or "\s+1".
        !           157:  */
        !           158: scanoptdel(cp, n) register char *cp; int n;
        !           159: {
        !           160:        register int c, retval;
        !           161:        static char buf[2];
        !           162: 
        !           163:        c = getf(0);
        !           164:        if (c != '-' && c != '+' && !isdigit(c)) {
        !           165:                buf[0] = c;
        !           166:                adscore(buf);                   /* push back c */
        !           167:                return scandel(cp, n);          /* and use scandel() */
        !           168:        }
        !           169:        retval = 1;
        !           170:        do {
        !           171:                if (--n == 0) {
        !           172:                        printe("delimiter argument too large");
        !           173:                        retval = 0;
        !           174:                } else
        !           175:                        *cp++ = c;
        !           176:                c = getf(0);
        !           177:        } while (isdigit(c));
        !           178:        buf[0] = c;
        !           179:        adscore(buf);                           /* push back nondigit */
        !           180:        return retval;
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * Given a buffer pointer, 'bp', and the size of the buffer, 'n',
        !           185:  * get an argument surrounded by delimiters and store it in the buffer.
        !           186:  */
        !           187: scandel(cp, n) register char *cp; int n;
        !           188: {
        !           189:        int retval;
        !           190:        register int c;
        !           191:        register int endc;
        !           192: 
        !           193:        retval = 1;
        !           194:        endc = getf(0);
        !           195:        while ((c=getf(0)) != endc) {
        !           196:                if (c == '\n') {
        !           197:                        printe("syntax error");
        !           198:                        return 0;
        !           199:                }
        !           200:                if (--n == 0) {
        !           201:                        printe("delimiter argument too large");
        !           202:                        retval = 0;
        !           203:                } else if (n > 0)
        !           204:                        *cp++ = c;
        !           205:        }
        !           206:        *cp++ = '\0';
        !           207:        return retval;
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * Get a character from the current input source.
        !           212:  * If EOF is seen: return EOF if eofflag, die if !eofflag.
        !           213:  */
        !           214: getl(eofflag) int eofflag;
        !           215: {
        !           216:        register STR *sp;
        !           217:        int n;
        !           218:        register int c;
        !           219:        register char *cp;
        !           220: 
        !           221:        sp = strp;
        !           222:        if (sp != NULL)
        !           223:                sp->x1.s_clnc = sp->x1.s_nlnc;
        !           224:        for (;;) {
        !           225:                if (sp == NULL) {
        !           226:                        if (eofflag == 0)
        !           227:                                panic("unexpected end of file");
        !           228:                        return EOF;
        !           229:                }
        !           230:                switch (sp->x1.s_type) {
        !           231:                case SSINP:
        !           232:                        if ((c=getc(stdin)) == EOF)
        !           233:                                break;
        !           234:                        if (c == '\0')
        !           235:                                break;
        !           236:                        if (c == '\n') {
        !           237:                                if ((c=getc(stdin)) == '\n')
        !           238:                                        c = '\0';
        !           239:                                ungetc(c, stdin);
        !           240:                                c = '\n';
        !           241:                        }
        !           242:                        goto ret;
        !           243:                case SFILE:
        !           244:                        if ((c=getc(sp->x2.s_fp)) == EOF) {
        !           245:                                fclose(sp->x2.s_fp);
        !           246:                                nfree(sp->x2.s_fname);
        !           247:                                break;
        !           248:                        }
        !           249:                        goto ret;
        !           250:                case SCORE:
        !           251:                        if ((c = *sp->x3.s_cp++) == '\0') {
        !           252:                                if (sp->x3.s_srel)
        !           253:                                        nfree(sp->x3.s_srel);
        !           254:                                break;
        !           255:                        }
        !           256:                        goto ret;
        !           257:                case SCTEX:
        !           258:                        if (sp->x4.s_disk  &&  sp->x4.s_sp >= sp->x4.s_bufend) {
        !           259:                                nread((long)sp->x4.s_seek,
        !           260:                                        (char *)sp->x4.s_bufp);
        !           261:                                sp->x4.s_seek += DBFSIZE;
        !           262:                                sp->x4.s_sp = sp->x4.s_bufp;
        !           263:                        }
        !           264:                        if ((c = *sp->x4.s_sp++) == '\0') {
        !           265:                                if (strnext())
        !           266:                                        continue;
        !           267:                                nfree(sp->x4.s_bufp);
        !           268:                                break;
        !           269:                        }
        !           270:                        goto ret;
        !           271:                case SCDIV:
        !           272:                        if (sp->x4.s_n-- == 0) {
        !           273:                                if (strnext())
        !           274:                                        continue;
        !           275:                                nfree(sp->x4.s_bufp);
        !           276:                                break;
        !           277:                        }
        !           278:                        n = sizeof (CODE);
        !           279:                        cp = (char *) &codeval;
        !           280:                        while (n--)
        !           281:                                *cp++ = geth();
        !           282:                        return ECOD;
        !           283:                }
        !           284:                if (sp->x4.s_abuf)
        !           285:                        nfree(sp->x4.s_abuf);
        !           286:                n = sp->x4.s_eoff;
        !           287:                strp = strp->x4.s_next;
        !           288:                nfree((char *)sp);
        !           289:                sp = strp;
        !           290:                if (n) {
        !           291:                        if (eofflag == 0)
        !           292:                                panic("incomplete macro in trap");
        !           293:                        return EOF;
        !           294:                }
        !           295:        }
        !           296: ret:
        !           297:        if ((c&=0377) == '\n')
        !           298:                sp->x4.s_nlnc++;
        !           299:        return c;
        !           300: }
        !           301: 
        !           302: /*
        !           303:  * In a chained macro, set up input stack to point to next element in chain.
        !           304:  */
        !           305: strnext()
        !           306: {
        !           307:        register STR *sp;
        !           308:        register MAC *mp;
        !           309: 
        !           310:        sp = strp;
        !           311:        if ((mp=sp->x4.s_macp) == NULL)
        !           312:                return 0;
        !           313:        sp->x4.s_macp = mp->t_div.m_next;
        !           314:        switch (mp->t_div.m_type) {
        !           315:        case MTEXT:
        !           316:                sp->x1.s_type = SCTEX;
        !           317:                break;
        !           318:        case MDIVN:
        !           319:                sp->x4.s_type = SCDIV;
        !           320:                if ((sp->x4.s_n=mp->t_div.m_size) == 0)
        !           321:                        return strnext();
        !           322:                break;
        !           323:        }
        !           324:        if (mp->t_div.m_core) {
        !           325:                sp->x4.s_disk = 0;
        !           326:                sp->x4.s_sp = mp->t_div.m_core;
        !           327:        } else {
        !           328:                sp->x4.s_disk = 1;
        !           329:                sp->x4.s_seek = mp->t_div.m_seek/DBFSIZE * DBFSIZE;
        !           330:                sp->x4.s_sp = &(sp->x4.s_bufp[mp->t_div.m_seek%DBFSIZE]);
        !           331:                nread((long)sp->x4.s_seek,(char *)sp->x4.s_bufp);
        !           332:                sp->x4.s_seek += DBFSIZE;
        !           333:        }
        !           334:        return 1;
        !           335: }
        !           336: 
        !           337: /*
        !           338:  * Get a single character assuming the stack has been set up
        !           339:  * for chained I/O.
        !           340:  */
        !           341: geth()
        !           342: {
        !           343:        if (strp->x4.s_disk  &&  strp->x4.s_sp >= strp->x4.s_bufend) {
        !           344:                nread((long)strp->x4.s_seek,(char *)strp->x4.s_bufp);
        !           345:                strp->x4.s_seek += DBFSIZE;
        !           346:                strp->x4.s_sp = strp->x4.s_bufp;
        !           347:        }
        !           348:        return (*strp->x4.s_sp++);
        !           349: }
        !           350: 
        !           351: /*
        !           352:  * Push down input stack and add the given file on top.
        !           353:  */
        !           354: adsfile(file)
        !           355: char *file;
        !           356: {
        !           357:        register STR *sp;
        !           358:        register FILE *fp;
        !           359: 
        !           360:        if ((fp = fopen(file, "r")) == NULL) {
        !           361:                printe("cannot open file \"%s\"", file);
        !           362:                return 0;
        !           363:        }
        !           364:        sp = allstr(SFILE);
        !           365:        sp->x2.s_fname = duplstr(file);
        !           366:        sp->x2.s_fp = fp;
        !           367:        return 1;
        !           368: }
        !           369: 
        !           370: /*
        !           371:  * Push down input stack and add the given FILE.
        !           372:  */
        !           373: adsunit(fp) FILE *fp;
        !           374: {
        !           375:        register STR *sp;
        !           376: 
        !           377:        sp = allstr(SFILE);
        !           378:        sp->x2.s_fname = duplstr("<stdin>");
        !           379:        sp->x2.s_fp = fp;
        !           380: }
        !           381: 
        !           382: /*
        !           383:  * Push down input stack and add the given register.
        !           384:  */
        !           385: adstreg(rp)
        !           386: register REG *rp;
        !           387: {
        !           388:        register STR *sp;
        !           389: 
        !           390:        if (rp->t_reg.r_macd.t_div.m_type == MREQS)
        !           391:                return 1;       /* return had been random, 1 is guess by cef */
        !           392:        sp = allstr(0);
        !           393:        sp->x4.s_bufp = nalloc(DBFSIZE);
        !           394:        sp->x4.s_bufend = &sp->x4.s_bufp[DBFSIZE];
        !           395:        sp->x4.s_macp = &rp->t_reg.r_macd;
        !           396:        if (strnext() == 0) {
        !           397:                strp = strp->x4.s_next;
        !           398:                nfree(sp->x4.s_bufp);
        !           399:                nfree((char *)sp);
        !           400:                return 0;
        !           401:        }
        !           402:        return 1;
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * Given the name of a special number register, expand it and
        !           407:  * add it onto the input stack.
        !           408:  */
        !           409: spcnreg(name)
        !           410: char name[2];
        !           411: {
        !           412:        register STR *sp;
        !           413:        register int n;
        !           414:        register char *cp;
        !           415: 
        !           416:        n = 0;
        !           417:        if (name[0] == '.') {
        !           418:                switch (name[1]) {
        !           419:                case '$':
        !           420:                        if ((n=strp->x1.s_argc) > 0)
        !           421:                                --n;
        !           422:                        break;
        !           423:                case 'A':       n = A_reg;                      break;
        !           424:                case 'F':                       /* Filename, not in V7. */
        !           425:                        for (sp=strp; sp; sp=sp->x1.s_next) {
        !           426:                                if (sp->x1.s_type == SFILE) {
        !           427:                                        adscore(sp->x2.s_fname);
        !           428:                                        return;
        !           429:                                }
        !           430:                        }
        !           431:                        return;
        !           432:                case 'H':       n = unit(SMHRES, SDHRES);       break;
        !           433:                /* case 'L': TO_DO */
        !           434:                /* case 'P': TO_DO */
        !           435:                case 'T':       n = T_reg;                      break;
        !           436:                case 'V':       n = unit(SMVRES, SDVRES);       break;
        !           437:                case 'a':       n = a_reg;                      break;
        !           438:                case 'c':
        !           439:                        n = 0;
        !           440:                        for (sp=strp; sp; sp=sp->x1.s_next) {
        !           441:                                if (sp->x1.s_type == SFILE) {
        !           442:                                        n = sp->x1.s_clnc;
        !           443:                                        break;
        !           444:                                }
        !           445:                        }
        !           446:                        break;
        !           447:                case 'd':       n = cdivp->d_rpos;              break;
        !           448:                case 'f':       n = 0;                          break;
        !           449:                case 'h':       n = cdivp->d_maxh;              break;
        !           450:                case 'i':       n = ind;                        break;
        !           451:                /* case 'j': TO_DO */
        !           452:                /* case 'k': TO_DO */
        !           453:                case 'l':       n = lln;                        break;
        !           454:                case 'n':       n = n_reg;                      break;
        !           455:                case 'o':       n = pof;                        break;
        !           456:                case 'p':       n = pgl;                        break;
        !           457:                case 's':       n = unit(psz*SDPOIN, SMPOIN);   break;
        !           458:                case 't':
        !           459:                        n = cdivp->d_ctpp ? cdivp->d_ctpp->t_apos : pgl;
        !           460:                        if (n > pgl)
        !           461:                                n = pgl;
        !           462:                        n -= cdivp->d_rpos;
        !           463:                        break;
        !           464:                case 'u':       n = fill;                       break;
        !           465:                case 'v':       n = vls;                        break;
        !           466:                case 'w':       n = 0;                          break;
        !           467:                case 'x':       n = 0;                          break;
        !           468:                case 'y':       n = 0;                          break;
        !           469:                case 'z':
        !           470:                        cp = nalloc(3);
        !           471:                        cp[0] = cdivp->d_name[0];
        !           472:                        cp[1] = cdivp->d_name[1];
        !           473:                        cp[2] = '\0';
        !           474:                        adscore(cp);
        !           475:                        strp->x3.s_srel = cp;
        !           476:                        return;
        !           477:                }
        !           478:        }
        !           479:        adsnval(n, '1');
        !           480: }
        !           481: 
        !           482: /*
        !           483:  * Given a value and a format, expand out the value to the
        !           484:  * particular format and add it onto the top of the stack.
        !           485:  */
        !           486: adsnval(val, f) int val, f;
        !           487: {
        !           488:        register ROM *op;
        !           489:        int w;
        !           490:        register int n;
        !           491:        char charbuf[CBFSIZE], *str, *cp2;
        !           492:        register char *cp1;
        !           493: 
        !           494:        n = val;
        !           495:        if (n <= 0) {
        !           496:                if ((n = -n) <= 0) {
        !           497:                        n = 0;
        !           498:                        if (!isdigit(f))
        !           499:                                f = '0';
        !           500:                }
        !           501:        }
        !           502:        cp1 = charbuf;
        !           503:        switch (f) {
        !           504:        case 'a':
        !           505:        case 'A':
        !           506:                while (n) {
        !           507:                        n--;
        !           508:                        *cp1++ = 'a' + n%26;
        !           509:                        n /= 26;
        !           510:                }
        !           511:                break;
        !           512:        case 'i':
        !           513:        case 'I':
        !           514:                for (cp2="ivxlcdm"; *cp2!='m'; cp2+=2) {
        !           515:                        op = &romtab[n%10];
        !           516:                        n /= 10;
        !           517:                        while (op != &romtab[0]) {
        !           518:                                *cp1++ = cp2[op->o_digit];
        !           519:                                op = &romtab[op->o_state];
        !           520:                        }
        !           521:                }
        !           522:                if (cp1+n >= &charbuf[CBFSIZE]) {
        !           523:                        *cp1++ = '*';
        !           524:                        break;
        !           525:                }
        !           526:                while (n--)
        !           527:                        *cp1++ = 'm';
        !           528:                break;
        !           529:        default:
        !           530:                w = f - '0';
        !           531:                while (n) {
        !           532:                        --w;
        !           533:                        *cp1++ = n%10 + '0';
        !           534:                        n /= 10;
        !           535:                }
        !           536:                while (w-- > 0)
        !           537:                        *cp1++ = '0';
        !           538:                if (val < 0)
        !           539:                        *cp1++ = '-';
        !           540:        }
        !           541:        cp2 = str = nalloc(cp1-charbuf + 1);
        !           542:        if (isupper(f)) {
        !           543:                while (cp1 > charbuf)
        !           544:                        if (islower(*--cp1))
        !           545:                                *cp2++ = toupper(*cp1);
        !           546:                        else    *cp2++ = *cp1;
        !           547:        } else {
        !           548:                while (cp1 > charbuf)
        !           549:                        *cp2++ = *--cp1;
        !           550:        }
        !           551:        *cp2 = '\0';
        !           552:        adscore(str);
        !           553:        strp->x3.s_srel = str;
        !           554: }
        !           555: 
        !           556: /*
        !           557:  * Divert input to the given string.
        !           558:  */
        !           559: adscore(cp) char *cp;
        !           560: {
        !           561:        register STR *sp;
        !           562: 
        !           563:        sp = allstr(SCORE);
        !           564:        sp->x3.s_cp = cp;
        !           565:        sp->x3.s_srel = NULL;
        !           566: }
        !           567: 
        !           568: /*
        !           569:  * Allocate an entry and add it to the input stack.
        !           570:  */
        !           571: STR *
        !           572: allstr(type)
        !           573: {
        !           574:        register STR *sp;
        !           575:        register int i;
        !           576: 
        !           577:        sp = (STR *) nalloc(sizeof *sp);
        !           578:        sp->x1.s_next = strp;
        !           579:        strp = sp;
        !           580:        sp->x1.s_type = type;
        !           581:        sp->x1.s_eoff = 0;
        !           582:        sp->x1.s_clnc = 1;
        !           583:        sp->x1.s_nlnc = 1;
        !           584:        sp->x1.s_argc = 0;
        !           585:        for (i = 0; i < ARGSIZE; i++)
        !           586:                sp->x1.s_argp[i] = "";
        !           587:        sp->x1.s_abuf = NULL;
        !           588:        return sp;
        !           589: }
        !           590: 
        !           591: hexdigit(c) register int c;
        !           592: {
        !           593:        if (isdigit(c))
        !           594:                return c - '0';
        !           595:        else if (c >= 'A' && c <= 'F')
        !           596:                return c - 'A' + 10;
        !           597:        else if (c >= 'a' && c <= 'f')
        !           598:                return c - 'a' + 10;
        !           599:        printe("illegal hex digit");
        !           600:        return 0;
        !           601: }
        !           602: 
        !           603:                
        !           604: /* end of getf.c */

unix.superglobalmegacorp.com

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