Annotation of researchv10no/cmd/dimpress/editrast.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*
                      3:  *
                      4:  * Simple scanner and recursive descent parser used to handle raster file
                      5:  * editing expressions.
                      6:  *
                      7:  * These were the last routines I wrote and by the time I got done it was
                      8:  * pretty clear that I should have written writevalue(), readvalue(), and
                      9:  * getvalue() a little differently. Anyway things seem to work OK even
                     10:  * though everything could have been better, so I'm not going to change
                     11:  * things right now.
                     12:  *
                     13:  */
                     14: 
                     15: 
                     16: #include <stdio.h>
                     17: #include <ctype.h>
                     18: 
                     19: #include "gen.h"                       /* general purpose definitions */
                     20: #include "rast.h"                      /* Imagen raster file definitions */
                     21: #include "buildrast.h"                 /* really just for Charinfor def */
                     22: #include "editrast.h"                  /* defs primarily used by scanner */
                     23: 
                     24: 
                     25: FILE           *fpin;                  /* everything comes from this FILE */
                     26: char           buf[50];                /* input buffer */
                     27: 
                     28: 
                     29: Tokens         tokens[] = {            /* tokens recognized by scanner */
                     30: 
                     31:        "=",            ASSIGNOP,
                     32:        "(",            LPAREN,
                     33:        ")",            RPAREN,
                     34:        "+",            PLUS,
                     35:        "-",            MINUS,
                     36:        "*",            TIMES,
                     37:        "/",            DIVIDE,
                     38:        "xref",         XREF,
                     39:        "yref",         YREF,
                     40:        "height",       HEIGHT,
                     41:        "width",        WIDTH,
                     42:        "chwidth",      CHWIDTH,
                     43:        "endedit",      ENDEDIT,
                     44:        "build",        BUILD
                     45: 
                     46: };
                     47: 
                     48: 
                     49: int            lasttoken;              /* code identifying last token read */
                     50: 
                     51: 
                     52: extern Charinfo        charinfo[];             /* used as the symbol table - sort of */
                     53: extern         first, last;            /* valid entries are in this closed interval */
                     54: 
                     55: 
                     56: /*
                     57:  *
                     58:  * Everything's done in floating point, so all the routines that handle the
                     59:  * parsing need to be declared as float.
                     60:  *
                     61:  */
                     62: 
                     63: 
                     64: float  expr(), exprprime(), term(), termprime(), factor();
                     65: 
                     66: 
                     67: /*****************************************************************************/
                     68: 
                     69: 
                     70: edit(fp)
                     71: 
                     72: 
                     73:     FILE       *fp;                    /* reading stuff from this file */
                     74: 
                     75: 
                     76: {
                     77: 
                     78: 
                     79:     char       name[20];               /* of the character we're editing */
                     80:     int                lhs_index;              /* location in charinfo[] */
                     81:     int                lhs_field;              /* field we want to change */
                     82:     int                value;                  /* of the expression */
                     83: 
                     84: 
                     85: /*
                     86:  *
                     87:  * Called when we want to process editing expressions from file *fp.
                     88:  *
                     89:  */
                     90: 
                     91: 
                     92:     fpin = fp;                         /* nexttoken() reads from fpin */
                     93: 
                     94:     nexttoken();                       /* loop assumes we've read first token */
                     95: 
                     96:     while ( lasttoken != ENDEDIT  &&  lasttoken != BUILD )  {
                     97: 
                     98:        if ( (lhs_field = lasttoken) != XREF && lhs_field != YREF && lhs_field != CHWIDTH )
                     99:            error(FATAL, "illegal assignment");
                    100: 
                    101:        fscanf(fpin, "%s", name);
                    102:        if ( (lhs_index = lookup(name)) == -1 )
                    103:            error(FATAL, "can't find character %s", name);
                    104: 
                    105:        nexttoken();                    /* better be an assignment operator */
                    106:        if ( lasttoken != ASSIGNOP )
                    107:            error(FATAL, "missing assignment operator");
                    108: 
                    109:        nexttoken();                    /* first token in the expression */
                    110:        value = expr() + .5;
                    111: 
                    112:        if ( lhs_field == XREF )
                    113:            writevalue(value, G_XREF, charinfo[lhs_index].glydir + rst[G_XREF].offset);
                    114:        else if ( lhs_field == YREF )
                    115:            writevalue(value, G_YREF, charinfo[lhs_index].glydir + rst[G_YREF].offset);
                    116:        else if ( lhs_field == CHWIDTH )
                    117:            charinfo[lhs_index].chwidth = value;
                    118: 
                    119:     }   /* End while */
                    120: 
                    121: }   /* End of edit */
                    122: 
                    123: 
                    124: /*****************************************************************************/
                    125: 
                    126: 
                    127: lookup(name)
                    128: 
                    129: 
                    130:     char       *name;                  /* find this guy in charinfo[] */
                    131: 
                    132: 
                    133: {
                    134: 
                    135: 
                    136:     int                i;                      /* loop index for lookups */
                    137: 
                    138: 
                    139: /*
                    140:  *
                    141:  * Looks for character *name in the charinfo[] array. If it's found its
                    142:  * index is returned to the caller, otherwise -1 is returned. We need to
                    143:  * know the values of first and last so we can properly restrict the search.
                    144:  * They're must be declared and set in whatever files use these routines.
                    145:  * For now it only includes buildrast.c, but we may want to make the editing
                    146:  * stuff more general.
                    147:  *
                    148:  */
                    149: 
                    150: 
                    151:     for ( i = first; i <= last; i++ )
                    152:        if ( strcmp(name, charinfo[i].name) == 0 )
                    153:            return(i);
                    154: 
                    155:     return(-1);
                    156: 
                    157: }   /* End of lookup */
                    158: 
                    159: 
                    160: /*****************************************************************************/
                    161: 
                    162: 
                    163: nexttoken()
                    164: 
                    165: 
                    166: {
                    167: 
                    168: 
                    169:     int                i;                      /* loop index for lookups in tokens[] */
                    170: 
                    171: 
                    172: /*
                    173:  *
                    174:  * Reads the input file *fpin looking for the next token. A code identifying
                    175:  * it is saved in lasttoken and the actual token string is saved in buf[].
                    176:  * If we reach EOF lasttoken will be set to ENDEDIT.
                    177:  *
                    178:  */
                    179: 
                    180: 
                    181:     if ( fscanf(fpin, "%1s", buf) == EOF )  {
                    182:        lasttoken = ENDEDIT;
                    183:        return;
                    184:     }  /* End if */
                    185: 
                    186:     if ( isdigit(buf[0]) )  {          /* must be a constant - integers only */
                    187:        fscanf(fpin, "%[0-9]", &buf[1]);
                    188:        lasttoken = CONSTANT;
                    189:        return;
                    190:     }  /* End if */
                    191: 
                    192:     if ( isalpha(buf[0]) )             /* get the rest of the token */
                    193:        fscanf(fpin, "%[a-zA-Z]", &buf[1]);
                    194: 
                    195:     for ( i = 0; i < sizeof(tokens); i++ )
                    196:        if ( strcmp(buf, tokens[i].str) == 0 )  {
                    197:            lasttoken = tokens[i].code;
                    198:            return;
                    199:        }   /* End if */
                    200: 
                    201:     error(FATAL, "don't recognize token %s", buf);
                    202: 
                    203: }    /* End of nexttoken */
                    204: 
                    205: 
                    206: /*****************************************************************************/
                    207: 
                    208: 
                    209: float expr()
                    210: 
                    211: 
                    212: {
                    213: 
                    214: 
                    215: /*
                    216:  *
                    217:  * Handles the productions:
                    218:  *
                    219:  *             EXPR -> TERM EXPR'
                    220:  *
                    221:  */
                    222: 
                    223: 
                    224:     return(exprprime(term()));
                    225: 
                    226: }   /* End of expr */
                    227: 
                    228: 
                    229: /*****************************************************************************/
                    230: 
                    231: 
                    232: float exprprime(val)
                    233: 
                    234: 
                    235:     float      val;                    /* add stuff to this guy */
                    236: 
                    237: 
                    238: {
                    239: 
                    240: 
                    241: /*
                    242:  *
                    243:  * Handles the productions:
                    244:  *
                    245:  *             EXPR' -> + TERM EXPR'
                    246:  *             EXPR' ->
                    247:  *
                    248:  */
                    249: 
                    250: 
                    251:     if ( lasttoken == PLUS )  {
                    252:        nexttoken();
                    253:        return(exprprime(val + term()));
                    254:     } else if ( lasttoken == MINUS )  {
                    255:        nexttoken();
                    256:        return(exprprime(val - term()));
                    257:     } else return(val);
                    258: 
                    259: }   /* End of exprprime */
                    260: 
                    261: 
                    262: /*****************************************************************************/
                    263: 
                    264: 
                    265: float term()
                    266: 
                    267: 
                    268: {
                    269: 
                    270: 
                    271: /*
                    272:  *
                    273:  * Handles the production:
                    274:  *
                    275:  *             TERM -> FACTOR TERM'
                    276:  *
                    277:  */
                    278: 
                    279: 
                    280:     return(termprime(factor()));
                    281: 
                    282: }   /* End of term */
                    283: 
                    284: 
                    285: /*****************************************************************************/
                    286: 
                    287: 
                    288: float termprime(val)
                    289: 
                    290: 
                    291:     float      val;                    /* value up to this point */
                    292: 
                    293: 
                    294: {
                    295: 
                    296: 
                    297: /*
                    298:  *
                    299:  * Handles the productions:
                    300:  *
                    301:  *             TERM' -> * FACTOR TERM'
                    302:  *             TERM' -> / FACTOR TERM'
                    303:  *             TERM' ->
                    304:  *
                    305:  */
                    306: 
                    307: 
                    308:     if ( lasttoken == TIMES )  {
                    309:        nexttoken();
                    310:        return(termprime(val * factor()));
                    311:     } else if ( lasttoken == DIVIDE )  {
                    312:        nexttoken();
                    313:        return(termprime(val / factor()));
                    314:     } else return(val);
                    315: 
                    316: }   /* End of termprime */
                    317: 
                    318: 
                    319: /*****************************************************************************/
                    320: 
                    321: 
                    322: float factor()
                    323: 
                    324: 
                    325: {
                    326: 
                    327: 
                    328:     float      val;                    /* value of the factor */
                    329: 
                    330: 
                    331: /*
                    332:  *
                    333:  * Handles the productions:
                    334:  *
                    335:  *             FACTOR -> ( EXPR )
                    336:  *             FACTOR -> - EXPR
                    337:  *             FACTOR -> CONSTANT
                    338:  *             FACTOR -> IDENT
                    339:  *
                    340:  */
                    341: 
                    342: 
                    343:     if ( lasttoken == CONSTANT )  {
                    344:        val = atoi(buf);
                    345:        nexttoken();
                    346:     } else if ( lasttoken == MINUS )
                    347:        val = exprprime(0);
                    348:     else if ( lasttoken == LPAREN )  {
                    349:        nexttoken();
                    350:        val = expr();
                    351:        if ( lasttoken == RPAREN )
                    352:            nexttoken();
                    353:        else error(FATAL, "expression syntax error - missing right paren");
                    354:     } else if ( lasttoken == XREF || lasttoken == YREF || lasttoken == HEIGHT || lasttoken == WIDTH || lasttoken == CHWIDTH )  {
                    355:        val = charvalue(lasttoken);
                    356:        nexttoken();
                    357:     } else error(FATAL, "syntax error - don't recognize factor");
                    358: 
                    359:     return(val);
                    360: 
                    361: }   /* End of factor */
                    362: 
                    363: 
                    364: /*****************************************************************************/
                    365: 
                    366: 
                    367: charvalue(tok)
                    368: 
                    369: 
                    370:     int                tok;                    /* number of the last token */
                    371: 
                    372: 
                    373: {
                    374: 
                    375: 
                    376:     char       name[20];               /* name of the character to lookup */
                    377:     int                i;                      /* its index in charinfo[] */
                    378: 
                    379: 
                    380: /*
                    381:  *
                    382:  * Called when we want to get the value of XREF, YREF, HEIGHT, WIDTH, or
                    383:  * CHWIDTH for a character. The guy we'll be looking up is the next string
                    384:  * in the input file.
                    385:  *
                    386:  * It's really clear that things, especially readvalue(), could have been
                    387:  * done better - sorry.
                    388:  *
                    389:  */
                    390: 
                    391: 
                    392:     fscanf(fpin, "%s", name);
                    393:     if ( (i = lookup(name)) == -1 )
                    394:        error(FATAL, "can't find character %s", name);
                    395: 
                    396:     if ( tok == XREF )
                    397:        return(readvalue(charinfo[i].glydir + rst[G_XREF].offset, rst[G_XREF].size, rst[G_XREF].type));
                    398:     else if ( tok == YREF )
                    399:        return(readvalue(charinfo[i].glydir + rst[G_YREF].offset, rst[G_YREF].size, rst[G_YREF].type));
                    400:     else if ( tok == HEIGHT )
                    401:        return(readvalue(charinfo[i].glydir + rst[G_HEIGHT].offset, rst[G_HEIGHT].size, rst[G_HEIGHT].type));
                    402:     else if ( tok == WIDTH )
                    403:        return(readvalue(charinfo[i].glydir + rst[G_WIDTH].offset, rst[G_WIDTH].size, rst[G_WIDTH].type));
                    404:     else error(FATAL, "CHWIDTH not implemented yet");
                    405: 
                    406: }   /* End of charvalue */
                    407: 
                    408: 
                    409: /*****************************************************************************/
                    410: 
                    411: 

unix.superglobalmegacorp.com

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