Annotation of coherent/d/bin/nroff/getf.c, revision 1.1.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.