Annotation of capa/capa51/pProj/capaUnit.c, revision 1.13

1.5       albertel    1: /* functions to handle the unit parser/comparison engine
                      2:    Copyright (C) 1992-2000 Michigan State University
                      3: 
                      4:    The CAPA system is free software; you can redistribute it and/or
1.7       albertel    5:    modify it under the terms of the GNU General Public License as
1.5       albertel    6:    published by the Free Software Foundation; either version 2 of the
                      7:    License, or (at your option) any later version.
                      8: 
                      9:    The CAPA system is distributed in the hope that it will be useful,
                     10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1.7       albertel   12:    General Public License for more details.
1.5       albertel   13: 
1.7       albertel   14:    You should have received a copy of the GNU General Public
1.5       albertel   15:    License along with the CAPA system; see the file COPYING.  If not,
                     16:    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.6       albertel   17:    Boston, MA 02111-1307, USA.
                     18: 
                     19:    As a special exception, you have permission to link this program
                     20:    with the TtH/TtM library and distribute executables, as long as you
                     21:    follow the requirements of the GNU GPL in regard to all of the
                     22:    software in the executable aside from TtH/TtM.
                     23: */
1.1       albertel   24: 
                     25: /* =||>|===================== capaUnit.c   =====================|<||= */
                     26: /*   created by Isaac Tsai   1997                                    */
1.6       albertel   27: /*   by Isaac Tsai 1997, 1998, 1999                      */
1.1       albertel   28: /* =||>|========================================================|<||= */
                     29: #include <stdio.h>        /* fopen()  */
                     30: #include <stdlib.h>
                     31: #include <ctype.h>        /* isalnum()   */
                     32: #include <string.h>
                     33: #include <math.h>
1.8       albertel   34: #include <float.h>
1.1       albertel   35: 
                     36: #include "capaParser.h"
                     37: 
                     38: int      PrefixTbl[QUARTER_K];
                     39: int      BaseUnitcnt;
                     40: double   CScale[BASEUNIT_LIMIT];
                     41: double   CExp[BASEUNIT_LIMIT];
                     42: char     CSymb[BASEUNIT_LIMIT][SYMBOL_MAXLEN];
                     43: Unit_t  *UnitTree_p;
                     44: double   MinSquared;
                     45: Unit_t  *MinSquaredUnit_p;
                     46: Unit_t  *InqueryUnit_p;
                     47: double  *TmpAexp, *TmpBexp;
                     48: Unit_t  *EquivUnit[BASEUNIT_LIMIT];
                     49: double   MinValue[BASEUNIT_LIMIT];
                     50: int      EquivUnitCnt;
                     51: char     Sbuf[ONE_K_SIZE];
                     52: int      Sidx;
                     53: Unit_t  *Pstack[ONE_K_SIZE];
                     54: int      Ptopidx;
                     55: int      gUnitError;
                     56: 
                     57: FILE    *ufp;
                     58: 
                     59: /* ==================================================================== */
                     60: void c_ignorewhite(FILE *f) /* ignore white spaces from a file stream */
                     61: {
                     62:   register int c;
                     63:   register int ok;
                     64:  
                     65:   ok = 0;
                     66:   do {
                     67:     do {  c = getc(f);
                     68:     } while ( isspace(c) );
                     69:     ungetc(c,f);
                     70:     if (c == '#') {
                     71:       while (getc(f) != '\n');
                     72:     } else ok = 1;
                     73:   } while( ! ok);
                     74: }
                     75: 
                     76: int c_getint(FILE *f)  /* returns an integer from the file stream */
                     77: {
                     78:     int c;
                     79:     int value;
                     80:  
                     81:     c_ignorewhite(f);
                     82:     c = fgetc(f);
                     83:     if (!isdigit(c)) {
                     84:         fprintf(stderr,"Error: Expected digit, got %c\n", c);
                     85:         exit(-1);
                     86:     }
                     87:     ungetc(c,f);
                     88:     fscanf(f,"%d", &value);
                     89:     return(value);
                     90: }
                     91: int c_getsec_range(FILE *f,int *low,int *high)
                     92: {
                     93:     int c;
                     94:     int tmp, result;
                     95:  
                     96:     c_ignorewhite(f);
                     97:     c = fgetc(f);
                     98:     if( c == '[' ) { /* specify a range of sections */
                     99:       do {  c = getc(f); } while ( isspace(c) );
                    100:       if (!isdigit(c)) {
                    101:         fprintf(stderr,"Error in section range format, expecting a number.\n");
                    102:         result = -1;
                    103:         return (result);
                    104:       }
                    105:       ungetc(c,f);
                    106:       fscanf(f,"%d", low);
                    107:       do {  c = getc(f); } while ( isspace(c) );
                    108:       if( c == ',' ) {
                    109:         do {  c = getc(f); } while ( isspace(c) );
                    110:         if (!isdigit(c)) {
                    111:           fprintf(stderr,"Error in section range format, expecting a number.\n");
                    112:           result = -1;
                    113:           return (result);
                    114:         }
                    115:         ungetc(c,f);
                    116:         fscanf(f,"%d", high);
                    117:         do {  c = getc(f); } while ( isspace(c) );
                    118:         if( c == ']' ) {
                    119:           if( *high < *low ) {
                    120:             tmp= *high; *high = *low; *low =tmp;
                    121:           }
                    122:           if(*low <=0) {
                    123:             *low = 1;
                    124:           }
                    125:           if(*high <=0) {
                    126:             *high =1;
                    127:           }
                    128:           /* printf("Section range=>[%d,%d]\n",*low,*high); */
                    129:           result = 2;
                    130:         }
                    131:       } else { /* no , specified */
                    132:         result = -1;
                    133:         return (result);
                    134:       }
                    135:     } else { /* specify a section only */
                    136:       if (!isdigit(c)) {
                    137:         fprintf(stderr,"Error: Expected digit, got %c\n", c);
                    138:         result = -1;
                    139:         return (result);
                    140:       }
                    141:       ungetc(c,f);
                    142:       fscanf(f,"%d", low);
                    143:       result = 1;
                    144:     }
                    145:     return (result);
                    146: }
                    147: 
                    148: double c_getdouble(FILE *f)
                    149: {
                    150:     int c;
                    151:     double value;
                    152:  
                    153:     c_ignorewhite(f);
                    154:     c = fgetc(f);
                    155:     if (!isdigit(c)) {
                    156:         fprintf(stderr,"Error: Expected digit, got %c\n", c);
                    157:         exit(-1);
                    158:     }
                    159:     ungetc(c,f);
                    160:     fscanf(f,"%lf", &value);
                    161:     return(value);
                    162: }
                    163: 
                    164: /*   read until encountered an unrecognizable char */
                    165: /*      space, #, anything other than alphanum, {}-^_ */
                    166: char *c_getword(FILE *f) 
                    167: {
                    168:   register int c;
                    169:   register int idx;
                    170:   char     tmp_string[ONE_K];
                    171:   char     *new_string;
                    172: 
                    173:   idx = 0;
                    174:   c_ignorewhite(f);
                    175:     do {  c = getc(f);
                    176:       tmp_string[idx] = c;
                    177:       idx++;
                    178:     } while (isalnum(c) || c == '{' || c == '}' || c == '-' || 
                    179:              c == '^'   || c == '_' );
                    180:     ungetc(c,f); idx--;
                    181:     tmp_string[idx] = 0;
                    182:     new_string = (char *)malloc( (idx+1)*sizeof(char) );
                    183:     strncpy(new_string,tmp_string, (idx+1) );
                    184:   
                    185:   return (new_string);
                    186: }
                    187: /*   read until encountered a newline, # */
                    188: char *c_getstring(FILE *f) 
                    189: {
                    190:   register int c;
                    191:   register int idx;
                    192:   char     tmp_string[1024];
                    193:   char     *new_string;
                    194: 
                    195:   idx = 0;
                    196:   c_ignorewhite(f);
                    197:     do {  c = getc(f);
                    198:       tmp_string[idx] = c;
                    199:       idx++;
                    200:     } while (isalnum(c) || c == '{' || c == '}' || c == '-' || 
                    201:              c == '^'   || c == ' ' || c == ',' || c == ';' ||
                    202:              c == '.'   || c == '(' || c == ')' || c == '=' ||
                    203:              c == '+'   || c == '*' || c == '/' );
                    204:     ungetc(c,f); idx--;
                    205:     tmp_string[idx] = 0;
                    206:     c = tmp_string[idx-1];
                    207:     while( c == ' ') {   /* get rid of trailing white space */
                    208:        idx--;
                    209:        c = tmp_string[idx-1];
                    210:     }
                    211:     tmp_string[idx] = 0;
                    212:     new_string = (char *)malloc( (idx+1)*sizeof(char) );
                    213:     strncpy(new_string,tmp_string, (idx+1) );
                    214:   
                    215:   return (new_string);
                    216: }
                    217: char *c_getcomment(FILE *f) 
                    218: {
                    219:   register int c;
                    220:   register int idx;
                    221:   char     tmp_string[ONE_K];
                    222:   char     *new_string;
                    223: 
                    224:   idx = 0;
                    225:   while (getc(f) != '#');
                    226:   while ((c = getc(f)) == ' ');  ungetc(c,f);
                    227:     do {  c = getc(f);
                    228:       tmp_string[idx] = c;
                    229:       idx++;
                    230:     } while ( isprint(c) );
                    231: /*
                    232:     } while (isalnum(c) || c == '{' || c == '}' || c == '-' || 
                    233:              c == '^'   || c == ' ' || c == ',' || c == ';' ||
                    234:              c == '.'   || c == '(' || c == ')' || c == '=' );
                    235: */
                    236:     ungetc(c,f); idx--;
                    237:     tmp_string[idx] = 0;
                    238:     c = tmp_string[idx-1];
                    239:     while( c == ' ') {   /* get rid of trailing white space */
                    240:        idx--;
                    241:        c = tmp_string[idx-1];
                    242:     }
                    243:     tmp_string[idx] = 0;
                    244:     new_string = (char *)malloc( (idx+1)*sizeof(char) );
                    245:     strncpy(new_string,tmp_string, (idx+1) );
                    246:   
                    247:   return (new_string);
                    248: }
                    249: void  c_moveto_unit(FILE *f)
                    250: {
                    251:   register int c;
                    252:   register int ok;
                    253:  
                    254:   ok = 0;
                    255:   do {
                    256:     do {  c = getc(f);
                    257:     } while (c != '<' );
                    258:     c = getc(f);
                    259:     if (c == '<') {
                    260:       ungetc(c,f); ungetc(c,f); ok=1;
                    261:     }
                    262:   } while( ! ok);
                    263: }
                    264: 
                    265: int  c_gettype(FILE *f)
                    266: {
                    267:   register int c;
                    268:   register int idx;
                    269:   char     tmp_string[ONE_K];
                    270:   char     new_string[ONE_K];
                    271:   
                    272:   idx = 0;
                    273: PRESTART:
                    274:   c_ignorewhite(f);
                    275:   while ((c=getc(f)) != '<') { if ( (char)c==(char)EOF ) return U_UNKNOWN; }
                    276:   c = getc(f);
                    277:   if( c == '<' ) {
                    278:     c_ignorewhite(f);
                    279: PREEND:
                    280:     do {  c = getc(f);
                    281:       tmp_string[idx] = toupper(c);
                    282:       idx++;
                    283:     } while ( c != '>' );
                    284:     c = getc(f); 
                    285:     if( c == '>' ) {
                    286:       idx--;
                    287:       tmp_string[idx] = 0;
                    288:       c = tmp_string[idx-1];
                    289:       while( c == ' ') {   /* get rid of trailing white space */
                    290:         idx--;
                    291:         c = tmp_string[idx-1];
                    292:       }
                    293:       tmp_string[idx] = 0;
                    294:       strncpy(new_string,tmp_string, (idx+1) );
                    295:     } else {
                    296:       ungetc(c,f);
                    297:       goto PREEND;
                    298:     }
                    299:   } else {
                    300:     goto PRESTART;
                    301:   }
                    302:   if( !strcmp(new_string,"BASE UNIT") ) {
                    303:     return (U_BASE);
                    304:   }  
                    305:   if( strcmp(new_string, "DERIVED UNIT") == 0 ) {
                    306:     return (U_DERIVED);
                    307:   }
                    308:   if( strcmp(new_string, "PREFIX") == 0 ) {
                    309:     return (U_PREFIX);
                    310:   }
                    311:   if( strcmp(new_string, "CONSTANTS") == 0 ) {
                    312:     return (U_CONSTANT);
                    313:   }
                    314:   if( strcasecmp(new_string, "DEFAULTS") == 0 ) {
                    315:     return (U_DEFAULT);
                    316:   }
                    317:   return (U_UNKNOWN);
                    318:   
                    319: }
                    320: 
                    321: /* =================================================================== */
                    322: /* =================================================================== */
                    323: /* returns: 0 success */
                    324: /*          1 the first units string u1_str could not be reduce to a valid unit */
                    325: /*          2 the second units string could not be reduced to a valid unit */
                    326: int
                    327: u_convert_unit(char *u1_str,char *u2_str,double *ratio)
                    328: {
                    329:   Unit_t   *ap, *bp;
                    330:   int       result=0;
                    331:   
                    332:   while( isspace(*u1_str) )  u1_str++;
                    333:   while( isspace(*u2_str) )  u2_str++;
                    334:   bp = parse_unit_expr(u2_str);
                    335:   Ptopidx=0;
                    336:   postwalk_utree(bp);
                    337:   if( Ptopidx == 1 ) {
                    338:     simplify_unit(Pstack[Ptopidx]);
                    339:     bp = Pstack[Ptopidx];
                    340:     /* print_unit_t(bp); */
                    341:     ap = parse_unit_expr(u1_str);
                    342:     Ptopidx=0;
                    343:     postwalk_utree(ap);
                    344:     if( Ptopidx == 1 ) {
                    345:       simplify_unit(Pstack[Ptopidx]);
                    346:       /* print_unit_t(Pstack[Ptopidx]); */
                    347:       if( (Pstack[Ptopidx]->u_count != 0) ||
                    348:           (Pstack[Ptopidx]->u_count == bp->u_count) ) { /* has unit */
                    349:         *ratio = units_ratio(Pstack[Ptopidx], bp);
                    350:       } else {
                    351:         result = 1;
                    352:       }
                    353:     }
                    354:     free_utree(ap);
                    355:   } else {
                    356:     result = 2;
                    357:   }
                    358:   free_utree(bp);
                    359:   return (result);
                    360: }
                    361: 
                    362: /* =================================================================== */
                    363: 
                    364: 
                    365: 
                    366: Unit_t *
                    367: u_find_symb (char *name, Unit_t *t, int *result) 
                    368: {
                    369:   
                    370:   if (t == NULL)  return t;
                    371: 
                    372:   for (;;) {
                    373:     if ( comp_unit_symb(name,t->u_symbol) < 0 ) {
                    374:       if (t->u_left == NULL)  {
                    375:         /* printf("L not found\n"); */
                    376:         *result = 0;
                    377:         break;
                    378:       }
                    379:       t = t->u_left;
                    380:     } else if ( comp_unit_symb(name,t->u_symbol) > 0 ) {
                    381:       if (t->u_right == NULL) {
                    382:         /* printf("R not found\n"); */
                    383:         *result = 0;
                    384:         break;
                    385:       }
                    386:       t = t->u_right;
                    387:     } else {
                    388:      *result = 1;
                    389:       break;
                    390:     }
                    391:   }
                    392:   return t;
                    393: }
                    394: /* ------------------------------------------------------------- */
                    395: /*   use the input unit_t's element list to locate the min squared */
                    396: /*   error fit of the unit tree        */
                    397: /*   report either exact fit or approx */
                    398: 
                    399: void
                    400: u_find_name(Unit_t *t)
                    401: {
                    402:   int      ii;
                    403:   Unit_E  *eu_p;
                    404:   
                    405:   MinSquared = FLT_MAX;
                    406:   EquivUnitCnt=0;
                    407:   InqueryUnit_p = t;
                    408:   /* printf("INQ[[%s,%s,%d]]\n", U_SYMB(t), U_NAME(t),U_COUNT(t)); */
                    409:   TmpAexp = (double *)capa_malloc(BaseUnitcnt,sizeof(double));
                    410:   TmpBexp = (double *)capa_malloc(BaseUnitcnt,sizeof(double));
                    411:   for(ii=0;ii<BaseUnitcnt;ii++) {
                    412:      TmpAexp[ii] = 0.0;
                    413:   }
                    414:   if( t->u_count > 0 ) {
                    415:     for(eu_p = t->u_list; eu_p; eu_p = eu_p->ue_nextp) {
                    416:       TmpAexp[eu_p->ue_index] = eu_p->ue_exp;
                    417:       /* printf("(%d)^(%g) ",eu_p->ue_index,TmpAexp[eu_p->ue_exp]); */
                    418:     }
                    419:     /* printf("\n"); */
                    420:   }
                    421:   inorder_diff(UnitTree_p);
                    422:   /*capa_mfree((char *)TmpAexp); capa_mfree((char *)TmpBexp);*/
                    423:   
                    424: }
                    425: 
                    426: void
                    427: print_matches(Unit_t *t)
                    428: {
                    429:   double   scale, factor;
                    430:   Unit_t  *tmp_p;
                    431:   int      ii;
                    432:   
                    433:   scale = t->u_scale;
                    434:   if( MinSquared == 0.0 ) {  /* exact match */
                    435:     if( EquivUnitCnt > 0 ) {
                    436:       printf(" Entered unit is equivalent to:\n");
                    437:       for(ii=0;ii<EquivUnitCnt;ii++) {
                    438:         tmp_p = EquivUnit[ii];
                    439:         if( MinSquared ==  MinValue[ii] ) {
                    440:           if( tmp_p->u_type == U_BASE ) {    /* if there is a base unit */
                    441:             MinSquaredUnit_p = tmp_p;
                    442:           }
                    443:           factor = scale / tmp_p->u_scale;
                    444:           printf(" <<%g %s>>", factor,U_SYMB(tmp_p));
                    445:         }
                    446:       }
                    447:       printf("\n");
                    448:       
                    449:     }
                    450:   } else {  /* no exact match */
                    451:     if( EquivUnitCnt > 0 ) {
                    452:       printf(" Entered unit is approximated by:\n");
                    453:       for(ii=0;ii<EquivUnitCnt;ii++) {
                    454:         tmp_p = EquivUnit[ii];
                    455:         if( MinSquared ==  MinValue[ii] ) {
                    456:           printf(" <<%s>> ", U_SYMB(tmp_p) );
                    457:         }
                    458:       }
                    459:       printf("\n");
                    460:     }
                    461:   }
                    462: }
                    463: 
                    464: /* ------------------------------------ */
                    465: double
                    466: u_squared_diff(Unit_t  *a, Unit_t *b)
                    467: {
                    468:   double   result;
                    469:   double   squared_diff = 0.0;
                    470:   int      ii;
                    471:   Unit_E  *eu_p;
                    472:   
                    473:   
                    474:   for(ii=0;ii<BaseUnitcnt;ii++) {
                    475:     TmpAexp[ii] = 0.0;
                    476:     TmpBexp[ii] = 0.0;
                    477:   }
                    478:   if( a->u_count > 0 ) {
                    479:     for(eu_p= a->u_list; eu_p; eu_p = eu_p->ue_nextp) {
                    480:       TmpAexp[eu_p->ue_index] = eu_p->ue_exp;
                    481:     }
                    482:   }
                    483:   if( b->u_count > 0 ) {
                    484:     for(eu_p= b->u_list; eu_p; eu_p = eu_p->ue_nextp) {
                    485:       TmpBexp[eu_p->ue_index] = eu_p->ue_exp;
                    486:       /* printf("Exp[%d]=%g ",ii,TmpBexp[ii]); */
                    487:     }
                    488:     /* printf("\n"); */
                    489:   }
                    490:   for(ii=0;ii<BaseUnitcnt;ii++) {
                    491:     result = TmpAexp[ii] - TmpBexp[ii];
                    492:     squared_diff = squared_diff + result*result;
                    493:   }
                    494:   
                    495:   return (squared_diff);
                    496: }
                    497: 
                    498: double
                    499: u_sq_diff(Unit_t *b)
                    500: {
                    501:   double   result;
                    502:   double   squared_diff = 0.0;
                    503:   int      ii;
                    504:   Unit_E  *eu_p;
                    505:   
                    506:   
                    507:   for(ii=0;ii<BaseUnitcnt;ii++) {
                    508:     TmpBexp[ii] = 0.0;
                    509:   }
                    510:   if( b->u_count > 0 ) {
                    511:     for(eu_p= b->u_list; eu_p; eu_p = eu_p->ue_nextp) {
                    512:       TmpBexp[eu_p->ue_index] = eu_p->ue_exp;
                    513:       /* printf("Exp[%d]=%g ",ii,TmpBexp[ii]); */
                    514:     }
                    515:     /* printf("\n"); */
                    516:   } else if( b->u_type == U_BASE  ) {
                    517:     TmpBexp[b->u_index] = 1.0;
                    518:   }
                    519:   for(ii=0;ii<BaseUnitcnt;ii++) {
                    520:     result = TmpAexp[ii] - TmpBexp[ii];
                    521:     squared_diff = squared_diff + result*result;
                    522:   }
                    523:   
                    524:   return (squared_diff);
                    525: 
                    526: }
                    527: /* ------------------------------------ */
                    528: 
                    529: int
                    530: inorder_diff(node_p) Unit_t  *node_p;
                    531: {
                    532:   int      result;
                    533:   double   sq_diff=0.0;
                    534:   
                    535:   if( node_p == NULL )  return (1);
                    536:   
                    537:   result = inorder_diff(U_LEFT(node_p));
                    538:   if( result ) {
                    539:      sq_diff = u_sq_diff(node_p);
                    540:      /*
                    541:      printf("DIFF [%s,%s,%d] - [%s,%s,%d] = %g\n", 
                    542:       U_SYMB(InqueryUnit_p), U_NAME(InqueryUnit_p),U_COUNT(InqueryUnit_p),
                    543:       U_SYMB(node_p), U_NAME(node_p),U_COUNT(node_p),sq_diff);
                    544:      */
                    545:      if( MinSquared > sq_diff) {
                    546:        MinSquaredUnit_p = node_p;
                    547:        MinSquared = sq_diff;
                    548:      } else if ( MinSquared == sq_diff) {
                    549:        EquivUnit[EquivUnitCnt] = node_p;
                    550:        MinValue[EquivUnitCnt] = sq_diff;
                    551:        EquivUnitCnt++;
                    552:      }
                    553:   }
                    554:   result = inorder_diff(U_RIGHT(node_p));
                    555:   
                    556:   return (result);
                    557: }
                    558: 
                    559: 
                    560: int
                    561: alphaorder_utree(node_p) Unit_t  *node_p;
                    562: {
                    563:   int  result;
                    564:   
                    565:   if( node_p == NULL )  return (1);
                    566:   
                    567:   result = alphaorder_utree(U_LEFT(node_p));
                    568:   if( result ) printf(" (%s,%s)\n", U_SYMB(node_p), U_NAME(node_p) );
                    569:   result = alphaorder_utree(U_RIGHT(node_p));
                    570:   
                    571:   return (result);
                    572: }
                    573: 
                    574: int
                    575: w_alphaorder_utree(node_p) Unit_t  *node_p;
                    576: {
                    577:   int  result;
                    578:   
                    579:   if( node_p == NULL )  return (1);
                    580:   
                    581:   result = alphaorder_utree(U_LEFT(node_p));
                    582:   if( result ) { 
                    583:      printf(" (%s,%s)\n", U_SYMB(node_p), U_NAME(node_p) );
                    584:   }
                    585:   result = alphaorder_utree(U_RIGHT(node_p));
                    586:   
                    587:   return (result);
                    588: }
                    589: 
                    590: /* --------------------------------------------------------------------- */
                    591: void
                    592: print_unit_tree(int mode)
                    593: {
                    594:   if( mode == 1 ) {
                    595:     alphaorder_utree(UnitTree_p);
                    596:   } else {
                    597:     w_alphaorder_utree(UnitTree_p);
                    598:   }
                    599: }
                    600: 
                    601: 
                    602: int
                    603: preorder_utree(node_p) Unit_t  *node_p;
                    604: {
                    605:   int  result;
                    606:   
                    607:   if( node_p == NULL )  return (1);
                    608:   printf("Preorder=[[%s,%s,%d]]\n", U_SYMB(node_p), U_NAME(node_p),U_COUNT(node_p));
                    609:   result = preorder_utree(U_LEFT(node_p));
                    610:   if( result ) result = preorder_utree(U_RIGHT(node_p));
                    611:   return (result);
                    612: }
                    613: int
                    614: inorder_utree(node_p) Unit_t  *node_p;
                    615: {
                    616:   int  result;
                    617:   
                    618:   if( node_p == NULL )  return (1);
                    619:   
                    620:   result = inorder_utree(U_LEFT(node_p));
                    621:   if( result ) printf("INorder=[[%s,%s,%d]]\n", 
                    622:     U_SYMB(node_p), U_NAME(node_p),U_COUNT(node_p));
                    623:   result = inorder_utree(U_RIGHT(node_p));
                    624:   
                    625:   return (result);
                    626: }
                    627: int
                    628: postorder_utree(node_p) Unit_t  *node_p;
                    629: {
                    630:   int  result;
                    631:   
                    632:   if( node_p == NULL )  return (1);
                    633:   
                    634:   result = postorder_utree(U_LEFT(node_p));
                    635:   if( result ) result = postorder_utree(U_RIGHT(node_p));
                    636:   if( result ) {
                    637:     switch(U_TYPE(node_p)) {
                    638:       case U_DERIVED:   print_unit_t(node_p);
                    639:             break;
                    640:       case U_CONSTANT:  printf("(%g)",U_SCALE(node_p));
                    641:             break;
                    642:       case U_OP_POWER:  printf("^");
                    643:             break;
                    644:       case U_OP_TIMES:  printf("*");
                    645:             break;
                    646:       case U_OP_PLUS:   printf("+");
                    647:             break;
                    648:       case U_OP_MINUS:  printf("-");
                    649:             break;
                    650:       case U_OP_DIVIDE: printf("/");
                    651:             break;
                    652:       default:          printf("()");
                    653:             break;  
                    654:     }
                    655:   }
                    656:   return (result);
                    657: }
                    658: 
1.4       albertel  659: /* returns 1 on okay, 2 on error*/
1.1       albertel  660: int
                    661: postwalk_utree(Unit_t  *n_p)
                    662: {
                    663:   int  result;
                    664:   
                    665:   if( n_p == NULL )  return (1);
                    666:   
                    667:   result = postwalk_utree(U_LEFT(n_p));
1.4       albertel  668:   if (result !=2) {
                    669:     if( result ) result = postwalk_utree(U_RIGHT(n_p));
                    670:     if (result !=2) {
                    671:       if( result ) {
                    672: 	switch(U_TYPE(n_p)) {
                    673: 	case U_DERIVED:   Ptopidx++; Pstack[Ptopidx] = n_p;  /* push into stack */
                    674: 	  break;
                    675: 	case U_CONSTANT:  Ptopidx++; Pstack[Ptopidx] = n_p;  /* push into stack */
                    676: 	  break;
                    677: 	case U_UNKNOWN:   result=2; 
                    678: 	  /*push into stack anyway, try to parse rest of tree */
                    679: 	  break;
                    680: 	case U_OP_POWER:  printf("^"); result=2;
                    681: 	  break;
                    682: 	case U_OP_TIMES:  process_op(U_OP_TIMES);        /* process operator */
                    683: 	  break;
                    684: 	case U_OP_PLUS:   printf("+"); result=2;
                    685: 	  break;
                    686: 	case U_OP_MINUS:  printf("-"); result=2;
                    687: 	  break;
                    688: 	case U_OP_DIVIDE: process_op(U_OP_DIVIDE);       /* process operator */
                    689: 	  break;
                    690: 	default:          printf("()"); result=2;
                    691: 	  break;  
                    692: 	}
                    693:       }
1.1       albertel  694:     }
                    695:   }
                    696:   return (result);
                    697: }
                    698: 
                    699: void
                    700: process_op(int op)
                    701: {
                    702:   Unit_t  *ap, *bp;
                    703:   double   exp_scale;
                    704:   int      no_error=1;
                    705:   
                    706:   bp = Pstack[Ptopidx--]; 
                    707:   ap = Pstack[Ptopidx--]; 
                    708:   
                    709:   switch(op) {
                    710:     case U_OP_TIMES:  exp_scale = 1.0;  break;
                    711:     case U_OP_DIVIDE: exp_scale = -1.0; break;
                    712:     case U_OP_PLUS:   
                    713:     case U_OP_MINUS:  no_error = u_pm_op(ap,bp,op);
                    714:                       if(no_error) {
                    715:                         Ptopidx++;
                    716:                         Pstack[Ptopidx] = ap;
                    717:                       }
                    718:                       break;
                    719:     default:          no_error=0; 
                    720:                       printf("No such op on the parse tree!\n");
                    721:           break;
                    722:   }
                    723:   if(no_error) {
                    724:     u_copy_unit(ap, bp, exp_scale);
                    725:     Ptopidx++;
                    726:     Pstack[Ptopidx] = ap;
                    727:   }
                    728: }
                    729: 
1.13    ! albertel  730: Unit_t*
1.1       albertel  731: process_utree(Unit_t *t)
                    732: {
                    733:   Ptopidx=0;
                    734:   postwalk_utree(t);
                    735:   if( Ptopidx == 1 ) {
1.13    ! albertel  736:     //fprintf(stderr,"Correctly parsed!\n");
        !           737:     //fprintf(stderr,"Unit:%s\n",Sbuf);
1.1       albertel  738:     simplify_unit(Pstack[Ptopidx]);
1.13    ! albertel  739:     //Pstack[Ptopidx]->u_symbol[0]='\0';
        !           740:     //fprintf(stderr,Pstack[Ptopidx]->u_symbol,"");
1.1       albertel  741:     print_unit_t(Pstack[Ptopidx]);
1.13    ! albertel  742:     //u_find_name(Pstack[Ptopidx]);
        !           743:     //print_matches(Pstack[Ptopidx]);
        !           744:     return(Pstack[Ptopidx]);
        !           745:     //free_utree(t);
1.1       albertel  746:   }
1.13    ! albertel  747:   return(t);
1.1       albertel  748: }
                    749: 
                    750: /* ============================================================== */
                    751: /*  called from capaCommon.c */
                    752: /*                      */
                    753: /*  UNIT_FAIL           */
                    754: /*  NO_UNIT             */
                    755: /*  result: UNIT_OK correct   */
                    756: /*                            */
                    757: /* -------------------------------------------------------------- */
                    758: int  check_correct_unit(char *u_symb,Unit_t *t,double *scale)
                    759: {
                    760:   Unit_t   *ap;
                    761:   int       result=UNIT_OK;
                    762: 
                    763: #ifdef UNIT_DBUG
1.4       albertel  764:    if ((ufp=fopen("unit.DBUG","a"))==NULL) { fprintf(stderr,"Error: can't open login debug\n"); return UNIT_FAIL; }
1.1       albertel  765: #endif 
                    766: 
1.3       albertel  767:   while( isspace(*u_symb) )  u_symb++; 
                    768:   /* <= change this to search from the end of string */
                    769:   /* or to get rid of all the white spaces */
                    770: 
                    771: 
1.1       albertel  772:   ap = parse_unit_expr(u_symb);
                    773:   Ptopidx=0;
1.4       albertel  774: 
                    775:   if (postwalk_utree(ap)==1) {
1.1       albertel  776: #ifdef UNIT_DBUG
1.4       albertel  777:     fprintf(ufp,"Ptopidx %d\n",Ptopidx);
1.1       albertel  778: #endif
1.4       albertel  779:     if( Ptopidx == 1 ) {
                    780:       simplify_unit(Pstack[Ptopidx]);
                    781:       
                    782:       if( (Pstack[Ptopidx]->u_count != 0) ||
                    783: 	  (Pstack[Ptopidx]->u_count == t->u_count) ) { /* has unit */
                    784: 	*scale = units_ratio(Pstack[Ptopidx], t);
                    785: 	if( *scale == 0.0 ) {
1.12      albertel  786: 	  result = UNIT_IRRECONCIBLE;
1.4       albertel  787: 	}
                    788: 	free_utree(ap);
                    789:       } else {
1.12      albertel  790: 	result = UNIT_INVALID_STUDENT3;
1.1       albertel  791:       }
1.4       albertel  792:     } else { /* invalid unit representation */
1.12      albertel  793:       result = UNIT_INVALID_STUDENT2;
1.1       albertel  794:     }
1.4       albertel  795:   } else {
1.12      albertel  796:     result = UNIT_INVALID_STUDENT1;
1.1       albertel  797:   }
                    798: #ifdef UNIT_DBUG
                    799:   fclose(ufp);
                    800: #endif 
                    801:   return (result);
                    802: }
                    803: 
                    804: /* ============================================================= */
                    805: int
                    806: free_units()
                    807: {
                    808:   free_utree(UnitTree_p);
                    809:   UnitTree_p=NULL;
                    810:   return 0;
                    811: }
                    812: 
                    813: int
                    814: free_utree(Unit_t  *t)
                    815: {
                    816:   int  result=1;
                    817:   
                    818:   if( t == NULL )  return (1);
                    819:   u_postfree(t);
                    820:   t=NULL;
                    821:   
                    822:   return (result);
                    823: }
                    824: 
                    825: 
                    826: int
                    827: u_postfree(Unit_t  *t)
                    828: {
                    829:   int  result;
                    830:   
                    831:   if( t == NULL )  return (1);
                    832:   
                    833:   result = u_postfree(U_LEFT(t));
                    834:   if( result ) result = u_postfree(U_RIGHT(t));
                    835:   if( result ) {
                    836:     if( t->u_comment ) {
                    837:       capa_mfree((char *)t->u_comment);
                    838:     }
                    839:     freelist_unit_e(t->u_list);
                    840:     capa_mfree((char *)t);
                    841:   }
                    842:   return (result);
                    843: }
                    844: 
                    845: 
                    846: void
                    847: print_unit_t(Unit_t *t) 
                    848: {
                    849:   Unit_E  *ue_p;
                    850: 
                    851:   /* printf("  Unit::[%s,%d]= %g * ", t->u_symbol,t->u_count,t->u_scale); */
                    852:   printf("  Unit::[%s] = %g * ", t->u_symbol, t->u_scale);
                    853:   for(ue_p=t->u_list; ue_p ; ue_p = ue_p->ue_nextp) {
                    854:     /*
                    855:     printf("<%s,%d,%g,%g> ",ue_p->ue_symbol,ue_p->ue_index,ue_p->ue_scale,ue_p->ue_exp);
                    856:     */
                    857:     printf("(%g*%s^%g) ",ue_p->ue_scale,ue_p->ue_symbol,ue_p->ue_exp);
                    858:   }
                    859:   printf("\n");
                    860: 
                    861: }
                    862: /*  ----------------------------------------------------------- */
                    863: /*  copy the Unit_E linked list from b_p->u_list to a_p->u_list */
                    864: /*   create some Unit_E nodes in a_p->u_list if needed and      */
                    865: /*   leave b_p->u_list intact                                   */
                    866: /*   a_p->u_scale is multiplied by pow(b_p->u_scale,exp_scale)  */
                    867: /*  ----------------------------------------------------------- */
                    868: void
                    869: u_copy_unit(Unit_t *a_p, Unit_t *b_p, double exp_scale) 
                    870: {
                    871:   Unit_E  *oe_p, *ne_p, *last_p;
                    872:   int      ii;
                    873:   double   scale;
                    874:   
                    875:   if( a_p->u_count > 0 ) {
                    876:     for(last_p = a_p->u_list; last_p->ue_nextp; last_p = last_p->ue_nextp) {  }
                    877:   } else {
                    878:     a_p->u_list = last_p = NULL;
                    879:   }
                    880:   if( b_p->u_count > 0 ) {
                    881:     oe_p = b_p->u_list;
                    882:     for(ii=0;ii<b_p->u_count;ii++) {
                    883:       ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E)); /* *** */
                    884:       ne_p->ue_scale = oe_p->ue_scale;
                    885:       ne_p->ue_exp   = oe_p->ue_exp * exp_scale;
                    886:       ne_p->ue_index = oe_p->ue_index;
                    887:       strcpy(ne_p->ue_symbol, oe_p->ue_symbol);
                    888:       oe_p = oe_p->ue_nextp;
                    889:       if( last_p == NULL ) {
                    890:         a_p->u_list = ne_p;
                    891:       } else {
                    892:         last_p->ue_nextp = ne_p;
                    893:       }
                    894:       last_p = ne_p;
                    895:       a_p->u_count++;
                    896:     }
                    897:     scale = pow(b_p->u_scale, exp_scale);
                    898:     a_p->u_scale = a_p->u_scale * scale;
                    899:     /* printf("Found scale=%g=%g\n",a_p->u_scale,b_p->u_scale); */
                    900:   } else {  
1.2       albertel  901:     if( b_p->u_type == U_BASE ) { 
1.1       albertel  902:       /* *b_p is a base unit, so create a one element unit */
                    903:       ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E));   /* *** */
                    904:       ne_p->ue_scale = b_p->u_scale;
                    905:       ne_p->ue_exp   = exp_scale;
                    906:       ne_p->ue_index = b_p->u_index;
                    907:       strcpy(ne_p->ue_symbol, b_p->u_symbol);
                    908:       if( last_p == NULL ) {
                    909:         a_p->u_list = ne_p;
                    910:       } else {
                    911:         last_p->ue_nextp = ne_p;
                    912:       }
                    913:       last_p = ne_p;
                    914:       a_p->u_count++;
1.2       albertel  915:     } else if( b_p->u_type == U_DERIVED) {
                    916:       /* derived units but without any units elements (scalar) */
1.4       albertel  917:       /*a_p->u_count++;*/
1.10      albertel  918:       scale = pow(b_p->u_scale, exp_scale);
                    919:       a_p->u_scale = a_p->u_scale * scale;
1.1       albertel  920:     } else if( b_p->u_type == U_CONSTANT ) {
                    921:       scale = pow(b_p->u_scale, exp_scale);
                    922:       a_p->u_scale = a_p->u_scale * scale;
                    923:     } else {
                    924:       printf("This node has no u_e list and Type unknown\n");
                    925:     }
                    926:   }
                    927: }
                    928: int
                    929: u_pm_op(Unit_t *a_p, Unit_t *b_p, int op)
                    930: {
                    931:   int    result=0;
                    932:   
                    933:   if( a_p->u_count > 0 || b_p->u_count > 0 ) {
                    934:      printf(" cannot add or sub units at this moment\n");
                    935:      return  result;
                    936:   }
                    937:   if( op == U_OP_PLUS ) {
                    938:     a_p->u_scale = a_p->u_scale + b_p->u_scale;
                    939:   } else {
                    940:     a_p->u_scale = a_p->u_scale - b_p->u_scale;
                    941:   }
                    942:   return 1;
                    943: }
                    944: 
                    945: int
                    946: u_parsepower(char *unit_str)
                    947: {
                    948:   int   exp, ii;
                    949:   char  *ch_p, exp_str[16];
                    950: 
                    951:   ch_p = unit_str;
                    952:   while( isspace(*ch_p) ) { ch_p++; }
                    953:   ii=0;
                    954:   while( isdigit(*ch_p) ) {
                    955:     ch_p++;
                    956:   }
                    957:   while( isspace(*ch_p) ) { ch_p++; }
                    958:   if( *ch_p == '^' ) {
                    959:     ch_p++;
                    960:   }
                    961:   while( isspace(*ch_p) ) { ch_p++; }
                    962:   if( *ch_p == '{' ) {
                    963:     ch_p++;
                    964:   }
                    965:   while( isspace(*ch_p) ) { ch_p++; }
                    966:   ii=0;
                    967:   while( isdigit(*ch_p) || *ch_p == '-' || *ch_p == '+' ) {
                    968:     exp_str[ii++] = *ch_p;
                    969:     ch_p++;
                    970:   }
                    971:   exp_str[ii]=0;
                    972:   sscanf(exp_str,"%d", &exp);
                    973:   return (exp);
                    974: }
                    975: 
                    976: /* ------------------------------------------- */
                    977: /* scan a number of the form indicated below from the input buffer */
                    978: /* 1.234^{2.3} */
                    979: /*  1e */
                    980: double
                    981: s_scan_number(char *buf, int idx, int *r_idx)
                    982: {
                    983:   double   num; 
                    984:   float    exp; 
                    985:   double   result;
                    986:   int      ii=0;
                    987:   char     num_str[QUARTER_K];
                    988:   
                    989:   num_str[ii]=0;
                    990:   
                    991:   if( buf[idx] == '-' ) {
                    992:     num_str[ii++] = '-';
                    993:     idx++;
                    994:   }
                    995:   while( isdigit(buf[idx]) || buf[idx] == '.' ) { 
                    996:       num_str[ii++] = buf[idx];
                    997:       idx++;
                    998:   }
                    999:   if( buf[idx] == 'E' || buf[idx] == 'e' ) {
                   1000:     if( buf[idx+1] == '-' || isdigit(buf[idx+1]) ) {
                   1001:       num_str[ii++] = buf[idx++];
                   1002:       num_str[ii++] = buf[idx++];
                   1003:       while( isdigit(buf[idx]) ) {
                   1004:         num_str[ii++] = buf[idx];
                   1005:         idx++;
                   1006:       }
                   1007:     }
                   1008:   }
                   1009:   num_str[ii] = 0; /* terminate the str */
                   1010:   sscanf(num_str,"%lg", &num);
                   1011:   /* printf("Scan number %s got %g\n",num_str, num); fflush(stdout); */
                   1012:   result = num;
                   1013:   if( buf[idx] == '^' ) {
                   1014:     idx++;
                   1015:     while( isspace(buf[idx]) ) { idx++; }
                   1016:     if( buf[idx] == '{' ) {  /* need to scan for a matching right bracket */
                   1017:         idx++;
                   1018:     }
                   1019:     while( isspace(buf[idx]) ) { idx++; }
                   1020:     num_str[0]=0;
                   1021:     if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {
                   1022:        ii=0;
                   1023:        while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
                   1024:          num_str[ii++] = buf[idx];
                   1025:          idx++;
                   1026:        }
                   1027:        num_str[ii]=0;
                   1028:     }
                   1029:     while( isspace(buf[idx]) ) { idx++; }
                   1030:     if( buf[idx] == '}' ) {
                   1031:       idx++;
                   1032:     }
                   1033:     sscanf(num_str,"%f", &exp);
                   1034:     /* printf("Scan exp number %s got %g\n",num_str, exp); fflush(stdout); */
                   1035:     
                   1036:     result = pow(num, (double)exp);
                   1037:     /* printf("{%d^%d}=%g\n",num, exp,result); */
                   1038:   }
                   1039:   *r_idx = idx;
                   1040:   return (result);
                   1041: }
                   1042: 
                   1043: 
                   1044: double
                   1045: s_scan_symbol(char *buf,char *symb_p,int idx, int *r_idx)
                   1046: {
                   1047:   char     num_str[QUARTER_K];
                   1048:   int      ii=0;
                   1049:   double   r_exp=1.0;
                   1050:   
                   1051:   symb_p[0]=0;
                   1052:   while( isalnum(buf[idx]) || buf[idx] == '_' ) {
                   1053:     symb_p[ii++] = buf[idx];
                   1054:     idx++;
                   1055:   }
                   1056:   symb_p[ii]=0;
                   1057:   
                   1058:   if( buf[idx] == '^' ) {  /* look for either left bracket or a number */
                   1059:     idx++;
                   1060:     while( isspace(buf[idx]) ) { idx++; } 
                   1061:     if( buf[idx] == '{' ) {  /* need to scan for a matching right bracket */
                   1062:       idx++;
                   1063:     }
                   1064:     while( isspace(buf[idx]) ) { idx++; }
                   1065:     if( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-'  )  {
                   1066:       ii=0; num_str[ii] = 0;
                   1067:       while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
                   1068:         num_str[ii++] = buf[idx];
                   1069:         idx++;
                   1070:       }
                   1071:       num_str[ii]=0;
                   1072:     }
                   1073:     while( isspace(buf[idx]) ) { idx++; }
                   1074:     if( buf[idx] == '}' ) {
                   1075:       idx++;
                   1076:     }
                   1077:     sscanf(num_str,"%lg", &r_exp);  /* power could be of type float */
                   1078:     /* printf("[scan symb with power %s ^ %lg] ",symb_p, r_exp); fflush(stdout);  */
                   1079:   }
                   1080:   *r_idx = idx;
                   1081:   return (r_exp);
                   1082: }
                   1083: 
                   1084: /*  return: err_code    0    parsed ok */
                   1085: /*                      1    symbol is of length 1, not found in the tree */
                   1086: /*                      2    symbol not found in the tree  */
                   1087: /*                      3    symbol parsed as prefix symb, but symb not found */
                   1088: /*                      4    symbol length is 0 or negative */
                   1089: int
                   1090: s_process_symb(char *symb_str,Unit_t  *cu_p,double exp)
                   1091: {
                   1092:   int      len;
                   1093:   Unit_t  *au_p;
                   1094:   int      c_result;
                   1095:   int      ii;
                   1096:   char     tmp_str[ANSWER_STRING_LENG];
                   1097:   int      err_code = 0;
                   1098:   double   d_exp;
                   1099:   
                   1100:   len = strlen(symb_str);
                   1101:   if( len > 0 ) {
                   1102:     au_p = u_find_symb(symb_str, UnitTree_p, &c_result);
                   1103:     if( c_result == 1 ) {  /* if found, copy the definition over */
                   1104:       u_copy_unit(cu_p, au_p, exp);
                   1105:     } else {
                   1106:       if( len > 1 ) {
                   1107:         if( PrefixTbl[ (int)symb_str[0] ] != 0 ) {  /* prefix is defined */
                   1108:           for(ii=1;ii<len;ii++) {
                   1109:              tmp_str[ii-1] = symb_str[ii];
                   1110:           }
                   1111:           tmp_str[len-1]=0;
                   1112:           au_p = u_find_symb(tmp_str, UnitTree_p, &c_result);
                   1113:           if( c_result == 1 ) {
                   1114:               /* printf("[%s] ", tmp_str); */
                   1115:             u_copy_unit(cu_p, au_p, exp);
                   1116:             d_exp = (double)PrefixTbl[ (int)symb_str[0] ] * exp;
                   1117:             cu_p->u_scale = cu_p->u_scale * pow((double)10.0,d_exp);
                   1118:           } else { /* unit *tmp_str not found */
                   1119:             /*printf("The unit: %s, not defined\n",tmp_str);*/
                   1120:             err_code = 3;
                   1121:           }
                   1122:         } else {
                   1123:           /*printf("<<%s>>", symb_str);*/
                   1124:           err_code = 2;
                   1125:         }
                   1126:       } else {/* len == 1 */
                   1127: 	/*printf("The unit: %s, not defined\n",symb_str);*/
                   1128:         err_code = 1;
                   1129:       }
                   1130:     }
                   1131:   } else {
                   1132:     err_code = 4;
                   1133:   }
                   1134:   return (err_code);
                   1135: }
                   1136: 
                   1137: Unit_t *
                   1138: u_parse_unit(char *unit_str)
                   1139: {
                   1140:   char      *ch;
                   1141:   char       symb_str[QUARTER_K];
                   1142:   int        idx;
                   1143:   double     exp_sign;
                   1144:   int        s_result;
                   1145:   int        not_done;
                   1146:   double     s_number,  offset;
                   1147:   double     tmp_scale, symb_exp, exp;
                   1148:   Unit_t    *cu_p;
                   1149: 
                   1150:   gUnitError=0;
                   1151:   ch   = unit_str;
                   1152:   cu_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t)); /* *** */
                   1153:   cu_p->u_scale = 1.0;
                   1154:   idx = 0;  not_done = 1;
                   1155:   exp_sign = 1.0; exp = 1;
                   1156:   symb_str[0] = 0;
                   1157: 
                   1158:   while( isspace(*ch) ) { ch++; }    /* trim leading white spaces */
                   1159:   /* fprintf(stdout,"PARSE |%s|\n", unit_str); */
                   1160:   while( not_done ) {
                   1161:     if( isdigit(ch[idx]) || ch[idx] == '-' ) {  /* rule 1: number */
                   1162:        s_number = s_scan_number(ch,idx,&idx);
                   1163:        
                   1164:        tmp_scale = pow(s_number,exp_sign);
                   1165:        /* printf("S=%g,Power(%g,%d)=%g\n", 
                   1166:           cu_p->u_scale, s_number,exp_sign, tmp_scale);
                   1167:        */
                   1168:        cu_p->u_scale = cu_p->u_scale * tmp_scale;
                   1169:        
                   1170:        /* printf("[Scale %g=%g^%g] ",tmp_scale,s_number,exp_sign); */
                   1171:        while( isspace(ch[idx]) ) { idx++; }
                   1172:     } else {
                   1173:       if( isalpha(ch[idx]) ) { /* rule 2: unit_symbol ^ exp */
                   1174: 	symb_str[0] = 0;
                   1175: 	symb_exp = s_scan_symbol(ch,symb_str,idx,&idx);
                   1176: 	exp = (double)exp_sign * symb_exp;
                   1177: 	/* printf("[scanned %s ^ (%g * %g)] ", symb_str,symb_exp,exp_sign); fflush(stdout); */
                   1178: 	s_result = s_process_symb(symb_str,cu_p,exp);
                   1179: 	if( s_result > 0 ) {
                   1180: 	  /* printf("Error processing symbol [%s]\n", symb_str); */
                   1181: 	  gUnitError = 1;
                   1182: 	}
                   1183: 	while( isspace(ch[idx]) ) { idx++; }
                   1184:       } else {
                   1185: 	if( ch[idx] == '*' || ch[idx] == '/' ) {
                   1186: 	  if( ch[idx] == '/' ) { /* printf("[/] "); */ exp_sign = -1.0; }
                   1187: 	  idx++;
                   1188: 	  while( isspace(ch[idx]) ) { idx++; }
                   1189: 	} else {
                   1190: 	  if( ch[idx] == '+' || ch[idx] == '-' ) {
                   1191: 	    idx++;
                   1192: 	    while( isspace(ch[idx]) ) { idx++; }
                   1193: 	    offset = s_scan_number(ch,idx,&idx);
                   1194: 	    /* printf("[Offset %g] ",offset); */
                   1195: 	  } else {
                   1196: 	    if( ch[idx] == 0 ) {  /* end of input string */
                   1197: 	      not_done = 0;
                   1198: 	      /* printf("\n"); */
                   1199: 	    } else {
                   1200: 	      /* garbage in unit string */
                   1201: 	      gUnitError = 1;
                   1202: 	      not_done=0;
                   1203: 	    }
                   1204: 	  }
                   1205: 	}
                   1206:       }
                   1207:     }
                   1208:   }
                   1209:   simplify_unit(cu_p);
                   1210:   return (cu_p);
                   1211: 
                   1212: }
                   1213: 
                   1214: void
                   1215: u_getunit(FILE *f)
                   1216: {
                   1217:   register int  unit_type;
                   1218:   register int  c;
                   1219:   int      power, result;
                   1220:   char   *name_p, *symbol_p, *comment_p, *unit_p;
                   1221:   
                   1222:   BaseUnitcnt = 0;
                   1223:   free_utree(UnitTree_p);
                   1224:   UnitTree_p = NULL;
                   1225:   c_moveto_unit(f);  /* move the file position to << */
                   1226:   do {
                   1227:     c_ignorewhite(f);
                   1228:     c = getc(f); ungetc(c,f);
                   1229:     if( c == '<' ) {
                   1230:       unit_type = c_gettype(f);
                   1231:     }
                   1232:     if( c != EOF ) {
                   1233:       switch(unit_type) {
                   1234:         case U_BASE:
                   1235:                name_p    = c_getword(f);    symbol_p = c_getword(f); 
                   1236:                comment_p = c_getcomment(f);
                   1237:                /*
                   1238:                printf("B Unit: N=%s,S=%s,C=%s\n",name_p,symbol_p,comment_p);
                   1239:                */
                   1240:                result = u_insert_baseunit(name_p,symbol_p,comment_p);
                   1241:                if( result == 1 ) {
                   1242:                  printf("The entry %s is duplicated\n",symbol_p);
                   1243:                }
                   1244:                free(name_p); free(symbol_p); free(comment_p);
                   1245:                break;
                   1246:         case U_DERIVED:
                   1247:                name_p    = c_getword(f);    symbol_p = c_getword(f);
                   1248:                unit_p    = c_getstring(f);  comment_p = c_getcomment(f);
                   1249:                /*
                   1250:                printf("D Unit: N=%s,S=%s,C=%s,U=%s\n",
                   1251:                        name_p,symbol_p,comment_p,unit_p);
                   1252:                */
                   1253:                result = u_insert_derived(name_p,symbol_p,comment_p,unit_p);
                   1254:                if( result == 1 ) {
                   1255:                  printf("The entry %s is duplicated\n",symbol_p);
                   1256:                }
                   1257:                /* preorder_utree(UnitTree_p); */ 
                   1258:                free(name_p); free(symbol_p); free(comment_p); free(unit_p);
                   1259:                break;
                   1260:         case U_PREFIX:
                   1261:                name_p    = c_getword(f);    symbol_p = c_getword(f);
                   1262:                unit_p    = c_getstring(f);
                   1263:                /*
                   1264:                printf("Prefix: N=%s,S=%s,U=%s\n",
                   1265:                        name_p,symbol_p,unit_p);
                   1266:                */
                   1267:                power = u_parsepower(unit_p);
                   1268:                PrefixTbl[ (int)(*symbol_p) ] = power;
                   1269:                /* printf("    P[%c]=%d\n",*symbol_p,power);  */
                   1270:                free(name_p); free(symbol_p); free(unit_p);
                   1271:                break;
                   1272:         case U_CONSTANT:
                   1273:                symbol_p = c_getword(f);  unit_p    = c_getstring(f);
                   1274:                comment_p = c_getcomment(f);
                   1275:                /*
                   1276:                printf("Const.: S=%s,C=%s,U=%s\n",
                   1277:                        symbol_p,comment_p,unit_p);
                   1278:                */
                   1279:                break;
                   1280:         case U_UNKNOWN:
                   1281:                /* printf("Unknown\n"); */
                   1282:                break;
                   1283:       }
                   1284:     }
                   1285:   } while ( c != EOF );
                   1286: 
                   1287: }
                   1288: 
                   1289: /* ----------------------------------------------------------------- */
                   1290: /* comparing unit symbol names should be case sensitive */
                   1291: int
                   1292: comp_unit_symb(a, b) char *a; char *b;
                   1293: {
                   1294:   return strncmp(a,b,SYMBOL_MAXLEN);
                   1295: }
                   1296: 
                   1297: 
                   1298: Unit_t *
                   1299: u_splay (char *name, Unit_t *t) 
                   1300: {
                   1301:   Unit_t     N;
                   1302:   Unit_t    *l, *r, *y;
                   1303: 
                   1304:   if (t == NULL)  return t;
                   1305:   N.u_left  = (Unit_t *)NULL;
                   1306:   N.u_right = (Unit_t *)NULL;
                   1307:   l = r = &N;
                   1308: 
                   1309:   for (;;) {
                   1310:     if ( comp_unit_symb(name,t->u_symbol) < 0 ) {
                   1311:       if (t->u_left == NULL)  break;
                   1312:       if ( comp_unit_symb(name, (t->u_left)->u_symbol ) < 0 ) {
                   1313:         y = t->u_left; t->u_left = y->u_right; y->u_right = t; t = y;
                   1314:         if (t->u_left == NULL) break;
                   1315:       }
                   1316:       r->u_left = t; r = t; t = t->u_left;
                   1317:     } else if ( comp_unit_symb(name,t->u_symbol) > 0 ) {
                   1318:         if (t->u_right == NULL) break;
                   1319:         if ( comp_unit_symb(name, (t->u_right)->u_symbol ) > 0 ) {
                   1320:           y = t->u_right; t->u_right = y->u_left; y->u_left = t; t = y;
                   1321:           if (t->u_right == NULL) break;
                   1322:         }
                   1323:         l->u_right = t; l = t; t = t->u_right;
                   1324:     } else {
                   1325:       break;
                   1326:     }
                   1327:   }
                   1328:   l->u_right = t->u_left; r->u_left = t->u_right; t->u_left = N.u_right;
                   1329:   t->u_right = N.u_left;
                   1330:   return t;
                   1331: }
                   1332: 
                   1333: 
                   1334: 
                   1335: /* returns: 0  correctly inserted */
                   1336: /*          -1 error */
                   1337: /*          1  duplicate entry    */
                   1338: 
                   1339: int
                   1340: u_insert_baseunit(n_p,s_p,c_p) char  *n_p, *s_p, *c_p;
                   1341: {
                   1342:   Unit_t   *new_p, *t;
                   1343:   int       len;
                   1344:  
                   1345:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t)); /* *** */
                   1346:   if (new_p == NULL) {
                   1347:       printf("Ran out of space\n");
                   1348:       return(-1);
                   1349:   }
                   1350:   strcpy(new_p->u_symbol, s_p);
                   1351:   strcpy(new_p->u_name, n_p);
                   1352:   len = strlen(c_p);
                   1353:   new_p->u_comment = (char *) capa_malloc((len+1), sizeof(char)); /* *** */
                   1354:   strcpy(new_p->u_comment,c_p);
                   1355:   BaseUnitcnt++;
                   1356:   new_p->u_index  = BaseUnitcnt;
                   1357:   new_p->u_type   = U_BASE;
                   1358:   new_p->u_scale  = 1.0;
                   1359:   new_p->u_offset = 0.0;
                   1360:   new_p->u_count  = 0;
                   1361:   new_p->u_list   = NULL;
                   1362:  
                   1363:   if (UnitTree_p == NULL) {  /* a new unit tree */
                   1364:       UnitTree_p = new_p;
                   1365:       return (0);
                   1366:   }
                   1367:   t = u_splay(s_p, UnitTree_p);
                   1368:   if ( comp_unit_symb(s_p,t->u_symbol) < 0 ) {
                   1369:         new_p->u_left = t->u_left; new_p->u_right = t;
                   1370:         t->u_left = NULL;
                   1371:         /* Splay_cnt++;  */
                   1372:         UnitTree_p = new_p;
                   1373:         return (0);
                   1374:   } else if ( comp_unit_symb(s_p,t->u_symbol) > 0 ) {
                   1375:         new_p->u_right = t->u_right; new_p->u_left = t;
                   1376:         t->u_right = NULL;
                   1377:         /* Splay_cnt++; */
                   1378:         UnitTree_p = new_p;
                   1379:         return (0);
                   1380:   } else {    /* name and t->u_symbol is the same, which means found it */
                   1381:         capa_mfree( (char *)new_p );
                   1382:         UnitTree_p = t;
                   1383:         return (1);
                   1384:   }
                   1385: }
                   1386: 
                   1387: 
                   1388: int
                   1389: u_insert_derived(n_p,s_p,c_p,u_p)char  *n_p, *s_p, *c_p, *u_p;
                   1390: {
                   1391:   Unit_t  *new_p, *t;
                   1392:   int      c_result, len;
                   1393:   
                   1394:   /* inorder_utree(UnitTree_p); */
                   1395:   t = u_splay(s_p, UnitTree_p);
                   1396:   UnitTree_p = t;
                   1397:   c_result = comp_unit_symb(s_p,t->u_symbol);
                   1398:   if ( c_result == 0 ) {
                   1399:     UnitTree_p = t;
                   1400:     return (1);
                   1401:   }
                   1402:   
                   1403:   /* prepare a new Unit_t */
                   1404:   new_p = u_parse_unit(u_p);
                   1405:   strcpy(new_p->u_symbol,s_p);
                   1406:   strcpy(new_p->u_name, n_p);
                   1407:   new_p->u_type = U_DERIVED;
                   1408:   len = strlen(c_p);
                   1409:   new_p->u_comment = (char *) capa_malloc((len+1), sizeof(char)); /* *** */
                   1410:   strcpy(new_p->u_comment,c_p);
                   1411:   
                   1412:   simplify_unit(new_p);
1.10      albertel 1413: #ifdef UNIT_DBUG
1.2       albertel 1414:   printf("Derived Unit:%s\n",new_p->u_name);
                   1415:   print_unit_t(new_p); 
1.10      albertel 1416: #endif
1.1       albertel 1417:   if (c_result < 0 ) {
                   1418:     new_p->u_left = t->u_left; new_p->u_right = t;
                   1419:     t->u_left = NULL;
                   1420:   } else {  /* c_result > 0 */
                   1421:     new_p->u_right = t->u_right; new_p->u_left = t;
                   1422:     t->u_right = NULL;
                   1423:   }
                   1424:   UnitTree_p = new_p;
                   1425:   
                   1426:   return (0);
                   1427:   
                   1428: }
                   1429: 
                   1430: void
                   1431: freelist_unit_e(Unit_E *ue_p) 
                   1432: {
                   1433:   Unit_E  *curr_p, *next_p;
                   1434:   
                   1435:   if( ue_p != NULL ) {
                   1436:     next_p = ue_p->ue_nextp;
                   1437:     curr_p = ue_p;
                   1438:     if( next_p == NULL ) {
                   1439:       capa_mfree((char *)curr_p);
                   1440:     } else {
                   1441:       for( curr_p = ue_p; next_p; curr_p = next_p, next_p = next_p->ue_nextp) {
                   1442:         capa_mfree((char *)curr_p);
                   1443:       }
                   1444:       capa_mfree((char *)curr_p);
                   1445:     }
                   1446:   }
                   1447: }
                   1448: void
                   1449: simplify_unit(u_p) Unit_t *u_p;
                   1450: {
                   1451:   Unit_E   *eu_p, *prev_p;
                   1452:   int       ii, idx;
                   1453:   
                   1454:   /* walk through u_list and replace those u_index = -1 with */
                   1455:   /* a linked list of basic unit. */
                   1456:   /* u_msort_main() the whole u_list */
                   1457:   /* combine those units with same u_index */
                   1458:   for(ii=0;ii<BaseUnitcnt;ii++) {
                   1459:     CScale[ii] = 0.0;
                   1460:     CExp[ii] = 0.0;
                   1461:   }
1.2       albertel 1462:   /*
                   1463:   printf("Before Simplify:: \n");
                   1464:   print_unit_t(u_p);
                   1465:   */
1.1       albertel 1466:   if( u_p->u_count > 0 ) {
                   1467:     
                   1468:     for(eu_p=u_p->u_list; eu_p; eu_p = eu_p->ue_nextp) {
                   1469:       idx = eu_p->ue_index;
                   1470:       if( CScale[idx] == 0.0 ) {
                   1471:         CScale[idx] = 1.0;
                   1472:         strcpy(CSymb[idx],eu_p->ue_symbol);
                   1473:       }
                   1474:       CScale[idx] = CScale[idx] * eu_p->ue_scale;
                   1475:       CExp[idx] = CExp[idx] + eu_p->ue_exp;
                   1476:     }
1.2       albertel 1477:     /* debugging 
1.1       albertel 1478:     for(ii=0;ii<BaseUnitcnt;ii++) {
                   1479:       if( CScale[ii] != 0.0 ) {
                   1480:         printf("(%d)%s,S=%g,E=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]);
                   1481:       }
1.2       albertel 1482:       if( CExp[ii] == 0.0 ) {
                   1483:         printf("(%d)%s,S=%g,Exp=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]);
                   1484:       }
1.1       albertel 1485:     }
                   1486:     */
                   1487:     freelist_unit_e(u_p->u_list);
                   1488:     prev_p = u_p->u_list = NULL;
                   1489:     u_p->u_count = 0;
                   1490:     for(ii=0;ii<BaseUnitcnt;ii++) {
                   1491:       if( CScale[ii] != 0.0 && CExp[ii] != 0) {
                   1492:         eu_p = (Unit_E *)capa_malloc(1,sizeof(Unit_E)); /* ***************** */
                   1493:         eu_p->ue_scale = 1.0;
                   1494:         eu_p->ue_exp = CExp[ii];
                   1495:         eu_p->ue_index = ii;
                   1496:         strcpy(eu_p->ue_symbol,CSymb[ii]);
                   1497:         if( prev_p == NULL) {
                   1498:           u_p->u_list = prev_p = eu_p;
                   1499:         } else {
                   1500:           prev_p->ue_nextp = eu_p;
                   1501:           prev_p = eu_p;
                   1502:         }
                   1503:         u_p->u_count++;
                   1504:       }
                   1505:     }
                   1506:   }
1.2       albertel 1507:   /* 
                   1508:   printf("After Simplify:: \n");
                   1509:   print_unit_t(u_p);
                   1510:   */
1.1       albertel 1511: }
                   1512: 
                   1513: /* before comparing two units, make sure they are of  basic form */
                   1514: /* compares if two units are equal */
                   1515: /* equality returns 1 */
                   1516: 
                   1517: int  is_units_equal(Unit_t *u1_p, Unit_t *u2_p)
                   1518: {
                   1519:   int      result=1;
                   1520:   Unit_E  *a_p, *b_p;
                   1521:   
                   1522:   if( (u1_p->u_count == u2_p->u_count) && 
                   1523:       (u1_p->u_scale == u2_p->u_scale) ) {
                   1524:     for(a_p=u1_p->u_list, b_p=u2_p->u_list;
                   1525:         a_p; a_p=a_p->ue_nextp, b_p=b_p->ue_nextp) {
                   1526:       if(a_p->ue_index != b_p->ue_index ||
                   1527:          a_p->ue_scale != b_p->ue_scale ||
                   1528:          a_p->ue_exp   != b_p->ue_exp ) {
                   1529:         result=0;
                   1530:         break;
                   1531:       }
                   1532:     }
                   1533:   } else {
                   1534:     result=0;
                   1535:   }
                   1536:   return (result);
                   1537: }
                   1538: /*     input : both are the simplest units */
                   1539: /*     result: 0.0 means they are not of euquvalent units */
                   1540: /*             the ratio of u1 / u2   */
                   1541: double  units_ratio(Unit_t *u1_p, Unit_t *u2_p)
                   1542: {
                   1543:   double   ratio=1.0;
                   1544:   Unit_E  *a_p, *b_p;
                   1545:   
                   1546:   if( (u1_p->u_count == u2_p->u_count) ) {
                   1547:     for(a_p=u1_p->u_list, b_p=u2_p->u_list;
                   1548:         a_p; a_p=a_p->ue_nextp, b_p=b_p->ue_nextp) {
                   1549:       if(a_p->ue_index != b_p->ue_index ||
                   1550:          a_p->ue_scale != b_p->ue_scale ||
                   1551:          a_p->ue_exp   != b_p->ue_exp ) {
                   1552:         ratio=0.0;
                   1553:         break;
                   1554:       }
                   1555:     }
                   1556:   } else {
                   1557:     ratio=0.0;
                   1558:   }
                   1559:   if( (ratio != 0.0) && (u2_p->u_scale != 0.0 )  ) {
                   1560:     ratio = u1_p->u_scale / u2_p->u_scale;
                   1561:   }
                   1562:   return (ratio);
                   1563: }
                   1564: 
                   1565: /* ------------- The Grammar of Units Parser --------------------
                   1566: 
                   1567:   scan_unit_expr()  -->  scan_basic_block()
                   1568:                     -->  scan_basic_block() '+' scan_basic_block() 
                   1569:                     -->  scan_basic_block() '-' scan_basic_block()
                   1570:  
                   1571:   scan_num_expr()   -->  scan_num_block()
                   1572:                     -->  scan_num_block() '+' scan_num_block()
                   1573:                     -->  scan_num_block() '-' scan_num_block()
                   1574:                     
                   1575:   scan_basic_block()-->  scan_basic_term()
                   1576:                     -->  scan_basic_term()  '*' scan_basic_term()
                   1577:                     -->  scan_basic_term()  ' ' scan_basic_term()
                   1578:                     -->  scan_basic_term()  '/' scan_basic_term()
                   1579: 
                   1580:   scan_num_block()  -->  scan_num_term()
                   1581:                     -->  scan_num_term()  '*' scan_num_term()
                   1582:                     -->  scan_num_term()  ' ' scan_num_term()
                   1583:                     -->  scan_num_term()  '/' scan_num_term()
                   1584:   
                   1585:   
                   1586:   scan_basic_term() -->  scan_unit_item()          
                   1587:                     -->  scan_num_item()
                   1588:                     -->  '(' scan_basic_block() ')'
                   1589:                     -->  '{' scan_basic_block() '}'
                   1590: 
                   1591:   scan_num_term()   -->  scan_num_item()<sp>*
                   1592:                     --> '-' scan_num_item()<sp>*
                   1593:                     --> '(' scan_num_expr() ')'
                   1594:                     --> '{' scan_num_expr() '}'
                   1595: 
                   1596:   scan_unit_item()  -->  UNIT<sp>*
                   1597:                     -->  UNIT<sp>*  '^' <sp>* scan_num_term()
                   1598:                     
                   1599:   scan_num_item()   -->  FLOAT<sp>*
                   1600:                     -->  FLOAT<sp>* '^' <sp>* scan_num_term()
                   1601:   
                   1602:   scan_FLOAT()      -->  [0-9]+([eE][+-]?[0-9]+)*
                   1603:   
                   1604:   p_new_unit()      -->  [a-Z]+[a-Z0-9_]*
                   1605:   
                   1606:   -----------------------------------------
                   1607:   U.expr  := B.block
                   1608:            | B.block '+' B.block
                   1609:            | B.block '-' B.block
                   1610:            
                   1611:   N.expr  := N.block 
                   1612:            | N.block '+' N.block
                   1613:            | N.block '-' N.block
                   1614:  
                   1615:  To allow for operations like (J/N)^2 or {N/m}^2 (N/J)^3 
                   1616:  
                   1617:  
                   1618:   B.block := B.term
                   1619:            | B.term ' ' B.term
                   1620:            | B.term '*' B.term
                   1621:            | B.term '/' B.term
                   1622:            
                   1623:   N.block := N.term 
                   1624:            | N.term ' ' N.term
                   1625:            | N.term '*' N.term
                   1626:            | N.term '/' N.term
                   1627:            
                   1628:   B.term  := U.item
                   1629:            | N.item
                   1630:            | '(' B.block ')'
                   1631:            | '{' B.block '}'
                   1632:            
                   1633:            | '(' B.block ')' ^ N.term
                   1634:            | '{' B.block '}' ^ N.term
                   1635:            
                   1636:   N.term  := N.item
                   1637:            | '-' N.item
                   1638:            | '(' N.expr ')'
                   1639:            | '{' N.expr '}'
                   1640:            
                   1641:   U.item  := UNIT
                   1642:            | UNIT '^' N.term
                   1643:            
                   1644:   N.item  := FLOAT
                   1645:            | FLOAT '^' N.term
                   1646:            
                   1647:   UNIT    := [a-Z]+[a-Z0-9_]*
                   1648:   
                   1649:   FLOAT   := [0-9]+([eE][+-]?[0-9]+)*
                   1650:   
                   1651:  ------------------------------------------------------------------- */
                   1652:  
                   1653: Unit_t *
                   1654: p_new_op(Unit_t *left_p, int op, Unit_t *right_p)
                   1655: {
                   1656:   Unit_t  *new_p;
                   1657:   
                   1658:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
                   1659:   if (new_p == NULL) {
                   1660:       printf("Ran out of space\n");
                   1661:       return(NULL);
                   1662:   }
                   1663:   new_p->u_left   = left_p;
                   1664:   new_p->u_right  = right_p;
                   1665:   new_p->u_scale  = 0.0;
                   1666:   new_p->u_type   = op;
                   1667:   new_p->u_offset = 0.0;
                   1668:   new_p->u_count  = 0;
                   1669:   new_p->u_list   = NULL;
                   1670:   
                   1671:   return (new_p);
                   1672: }
                   1673: 
                   1674: Unit_t *
                   1675: p_new_num(Unit_t *left_p, double num, Unit_t *right_p)
                   1676: {
                   1677:   Unit_t  *new_p;
                   1678:   
                   1679:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
                   1680:   if (new_p == NULL) {
                   1681:       printf("Ran out of space\n");
                   1682:       return(NULL);
                   1683:   }
                   1684:   
                   1685:   new_p->u_left   = left_p;
                   1686:   new_p->u_right  = right_p;
                   1687:   new_p->u_scale  = num;
                   1688:   new_p->u_type   = U_CONSTANT;
                   1689:   new_p->u_offset = 0.0;
                   1690:   new_p->u_count  = 0;
                   1691:   new_p->u_list   = NULL;
                   1692:   
                   1693:   return (new_p);
                   1694: }
                   1695: 
                   1696: Unit_t *
                   1697: p_new_unit(Unit_t *left_p, Unit_t *right_p)
                   1698: {
                   1699:   char     symb_str[ANSWER_STRING_LENG];
                   1700:   int      ii=0;
                   1701:   int      len;
                   1702:   Unit_t  *au_p, *cu_p;
                   1703:   int      c_result;
                   1704:   char     tmp_str[ANSWER_STRING_LENG];
                   1705:   int      err_code = 0;
                   1706:   double   d_exp;
                   1707:   
                   1708:   symb_str[ii]=0;
                   1709:   while( isspace(Sbuf[Sidx]) ) { Sidx++; }
                   1710:   while( isalnum(Sbuf[Sidx]) || Sbuf[Sidx] == '_' ) {
                   1711:     symb_str[ii++] = Sbuf[Sidx];
                   1712:     Sidx++;
                   1713:   }
                   1714:   symb_str[ii]=0;
                   1715:   /* printf("<U %s>", symb_str); */
                   1716:   cu_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
                   1717:   strcpy(cu_p->u_symbol,symb_str);
                   1718:   cu_p->u_left   = left_p;
                   1719:   cu_p->u_right  = right_p;
                   1720:   cu_p->u_scale  = 1.0;
                   1721:   cu_p->u_type   = U_DERIVED;
                   1722:   cu_p->u_offset = 0.0;
                   1723:   cu_p->u_count  = 0;
                   1724:   cu_p->u_list   = NULL;
                   1725:   
                   1726:   len = strlen(symb_str);
                   1727:   if( len > 0 ) {
                   1728:     au_p = u_find_symb(symb_str, UnitTree_p, &c_result);
                   1729:     if( c_result == 1 ) {  /* if found, copy the definition over */
                   1730:       u_copy_unit(cu_p, au_p, 1);
                   1731:     } else {
                   1732:       if( len > 1 ) {
                   1733:         if( PrefixTbl[ (int)symb_str[0] ] != 0 ) {  /* prefix is defined */
                   1734:           for(ii=1;ii<len;ii++) {
                   1735:              tmp_str[ii-1] = symb_str[ii];
                   1736:           }
                   1737:           tmp_str[len-1]=0;
                   1738:           au_p = u_find_symb(tmp_str, UnitTree_p, &c_result);
                   1739:           if( c_result == 1 ) {
                   1740:               /* printf("[%s] ", tmp_str); */
                   1741:             u_copy_unit(cu_p, au_p, 1);
                   1742:             d_exp = (double)PrefixTbl[ (int)symb_str[0] ];
                   1743:             cu_p->u_scale = cu_p->u_scale * pow((double)10.0,d_exp);
                   1744:           } else { /* unit *tmp_str not found */
                   1745:             /* printf(" not found\n"); */
                   1746:             err_code = 3;
1.4       albertel 1747: 	    cu_p->u_type   = U_UNKNOWN;
1.1       albertel 1748:           }
1.9       albertel 1749:         } else { /* symb_str is not in <prefix><units> form */
1.1       albertel 1750:           /* printf("<<%s>>", symb_str); */
                   1751:           err_code = 2;
1.4       albertel 1752: 	  cu_p->u_type   = U_UNKNOWN;
1.1       albertel 1753:         }
                   1754:       } else {/* len == 1 */
1.9       albertel 1755:         /* printf(" not found in symbol tree \n"); */
1.1       albertel 1756:         err_code = 1;
1.4       albertel 1757: 	cu_p->u_type   = U_UNKNOWN;
1.1       albertel 1758:       }
                   1759:     }
1.9       albertel 1760:   } else { /* why would we have a length less than zero symb_str ? */
1.1       albertel 1761:     err_code = 4;
                   1762:   }
                   1763:   
                   1764:   return (cu_p);
                   1765: }
                   1766: 
                   1767: int  s_peeknext_op()
                   1768: {
                   1769:   char  *ch;
                   1770:   int    sp=0;
                   1771:   
                   1772:   ch = (char *)&Sbuf[Sidx];
                   1773:   while( isspace(*ch) ) { ch++; sp=1; }
                   1774:   if( (*ch == '*')  || (*ch == '/') || (*ch == '+')  || (*ch == '-') || (*ch == '^')) {
                   1775:     return (*ch);
                   1776:   }
                   1777:   /* what if space is the last thing on the line?*/
                   1778:   if( sp && (*ch != '\0')) return '*';
                   1779:   return (*ch);
                   1780: }
                   1781: 
                   1782: int  s_getnext_op()
                   1783: {
                   1784:   char  *ch;
                   1785:   int    inc = 0, sp=0;
                   1786:   
                   1787:   
                   1788:   /* printf("\n((op"); print_remains(); printf("\n");  */
                   1789:   ch = (char *)&Sbuf[Sidx];
                   1790:   while( isspace(*ch) ) { ch++; inc++; sp=1; }
                   1791:   Sidx = Sidx + inc;
                   1792:   if( (*ch == '*')  || (*ch == '/') || (*ch == '+')  || (*ch == '-') || (*ch == '^') ) {
                   1793:     Sidx++;
                   1794:     /* print_remains();  printf(" op))"); printf("\n"); */
                   1795:     return (*ch);
                   1796:   }
                   1797:   /* print_remains();  printf(" op))"); printf("\n"); */
                   1798:   /* what if space is the last thing on the line?*/
                   1799:   if( sp  && (*ch != '\0')) return '*';
                   1800:   return (*ch);
                   1801: }
                   1802: 
                   1803: int
                   1804: s_getnext()
                   1805: {
                   1806:   char  ch;
                   1807:   
                   1808:   ch = Sbuf[Sidx];
                   1809:   Sidx++;
                   1810:   return (ch);
                   1811: }
                   1812: 
                   1813: int
                   1814: s_peeknext()
                   1815: {
                   1816:   char  ch;
                   1817:   
                   1818:   ch = Sbuf[Sidx];
                   1819:   return (ch);
                   1820: }
                   1821: 
                   1822: int
                   1823: s_peeknextNW()  /* peek into the next non-whitespaces character */
                   1824: {
                   1825:   char  *ch;
                   1826: 
                   1827:   ch = (char *)&Sbuf[Sidx];
                   1828:   while( isspace(*ch) ) { ch++; }
                   1829:   return (*ch);
                   1830: }
                   1831: 
                   1832: int
                   1833: s_getnextNW()  /* get the next non-whitespaces character */
                   1834: {
                   1835:   char  *ch;
                   1836: 
                   1837:   ch = (char *)&Sbuf[Sidx]; Sidx++;
                   1838:   while( isspace(*ch) ) { ch++; Sidx++; }
                   1839:   return (*ch);
                   1840: }
                   1841: /* peek into the next non-whitespaces character 
                   1842:    which should be either a multiply or division */
                   1843: int
                   1844: s_peekMDWS()  
                   1845: {
                   1846:   char  *ch;
                   1847:   int    sp=0;
                   1848:   
                   1849:   ch = (char *)&Sbuf[Sidx];
                   1850:   while( isspace(*ch) ) { ch++; sp=1;}
                   1851:   if( (*ch == '*')  || (*ch == '/') ) {
                   1852:     return (*ch);
                   1853:   }
                   1854:   if( sp ) return ' ';
                   1855:   ch = (char *)&Sbuf[Sidx];
                   1856:   while( isspace(*ch) ) { ch++; }
                   1857:   return (*ch);
                   1858: }
                   1859: 
                   1860: int
                   1861: s_getnextMDWS()
                   1862: {
                   1863:   char  *ch;
                   1864:   int    inc=0, sp=0;
                   1865:   
                   1866:   ch = (char *)&Sbuf[Sidx]; Sidx++;
                   1867:   while( isspace(*ch) ) { ch++; inc++; sp=1; }
                   1868:   Sidx += inc;
                   1869:   if( (*ch == '*')  || (*ch == '/') ) {
                   1870:     return (*ch);
                   1871:   }
                   1872:   if( sp ) return ' ';
                   1873:   return (*ch);
                   1874: }
                   1875: 
                   1876: double
                   1877: scan_FLOAT()
                   1878: {
                   1879:   double   num; 
                   1880:   int      ii=0, len;
                   1881:   char     num_str[QUARTER_K];
                   1882:   
                   1883:   num_str[ii]=0;
                   1884:   while( isspace(Sbuf[Sidx]) ) { Sidx++; }
                   1885:   if( Sbuf[Sidx] == '-' ) {
                   1886:     num_str[ii++] = Sbuf[Sidx++];
                   1887:   }
                   1888:   while( isdigit(Sbuf[Sidx]) || Sbuf[Sidx] == '.' ) {
                   1889:       num_str[ii++] = Sbuf[Sidx++];
                   1890:   }
                   1891:   if( Sbuf[Sidx] == 'E' || Sbuf[Sidx] == 'e' ) {
                   1892:     if( Sbuf[Sidx+1] == '-' || isdigit(Sbuf[Sidx+1]) ) {
                   1893:       num_str[ii++] = Sbuf[Sidx++];
                   1894:       num_str[ii++] = Sbuf[Sidx++];
                   1895:       while( isdigit(Sbuf[Sidx]) ) {
                   1896:         num_str[ii++] = Sbuf[Sidx++];
                   1897:       }
                   1898:     }
                   1899:   }
                   1900:   num_str[ii] = 0; /* terminate the str */
                   1901:   len = strlen(num_str);
                   1902:   if(len > 0 ) {
                   1903:     sscanf(num_str,"%lg", &num);
                   1904:     /* printf("<N %s %g>",num_str,num); fflush(stdout);  print_remains(); */
                   1905:   } else {
                   1906:     num = 1.0;
                   1907:   }
                   1908:   return (num);
                   1909: }
                   1910: /* -----------------------------------------------
                   1911:   N.item  := FLOAT
                   1912:            | FLOAT '^' N.term
                   1913:    ----------------------------------------------- */
                   1914: Unit_t  *
                   1915: scan_num_item()
                   1916: {
                   1917:   Unit_t  *node_p, *exp_p;
                   1918:   double   num_const;
                   1919:   char     ch;
                   1920:   
                   1921:   num_const = scan_FLOAT();
                   1922:   node_p = p_new_num(NULL, num_const, NULL);
                   1923:   ch = s_peeknext_op();
                   1924:   if( ch == '^' ) {
                   1925:     ch = s_getnext_op();
                   1926:     
                   1927:     exp_p = scan_num_term();
                   1928:     num_const = node_p->u_scale;
                   1929:     if( node_p->u_scale > 0.0 ) {
                   1930:       num_const = pow(node_p->u_scale,exp_p->u_scale);
                   1931:     }
                   1932:     node_p->u_scale = num_const;
                   1933:     capa_mfree((char *)exp_p);
                   1934:   }
                   1935:   return node_p;
                   1936: }
                   1937: 
                   1938: /* -----------------------------------------------
                   1939:   U.item  := UNIT
                   1940:            | UNIT '^' N.term
                   1941:    ----------------------------------------------- */
                   1942:    
                   1943: Unit_t *
                   1944: scan_unit_item()
                   1945: {
                   1946:   Unit_t   *node_p, *exp_p;
                   1947:   char      ch;
                   1948:   double   num_const;
                   1949:   Unit_E   *oe_p;
                   1950:   
                   1951:   node_p = p_new_unit(NULL,NULL);
                   1952:   ch = s_peeknext_op();
                   1953:   if( ch == '^' ) {
                   1954:     ch = s_getnext_op();
                   1955:     exp_p = scan_num_term();
                   1956:     num_const = exp_p->u_scale;
                   1957:     if( node_p->u_count > 0 ) {
                   1958:       oe_p = node_p->u_list;
                   1959:       for(oe_p = node_p->u_list; oe_p; oe_p = oe_p->ue_nextp ) {
                   1960:         oe_p->ue_exp   = oe_p->ue_exp * num_const;
                   1961:       }
                   1962:     }
                   1963:     num_const = node_p->u_scale;
                   1964:     if( node_p->u_scale > 0.0 ) {
                   1965:       num_const = pow(node_p->u_scale,exp_p->u_scale);
                   1966:     }
                   1967:     node_p->u_scale = num_const;
                   1968:     capa_mfree((char *)exp_p);
                   1969:   }
                   1970:   return node_p;
                   1971: }
                   1972: 
                   1973: void distribute_exp(Unit_t* node_p,Unit_t* exp_p) 
                   1974: {
                   1975:   Unit_E* oe_p;
                   1976:   double num_const;
                   1977:   num_const = exp_p->u_scale;  /* should we check if num_const too large or small ? */
                   1978:   if( node_p->u_count > 0 ) {
                   1979:     oe_p = node_p->u_list;
                   1980:     for(oe_p = node_p->u_list; oe_p; oe_p = oe_p->ue_nextp ) {
                   1981:       oe_p->ue_exp   = oe_p->ue_exp * num_const;
                   1982:     }
                   1983:   }
                   1984:   num_const = node_p->u_scale;
                   1985:   if( node_p->u_scale > 0.0 ) {  /* what if u_scale <= 0.0 ? */
                   1986:     num_const = pow(node_p->u_scale,exp_p->u_scale);
                   1987:   }
                   1988:   node_p->u_scale = num_const;
                   1989:   if (node_p->u_left) distribute_exp(node_p->u_left,exp_p);
                   1990:   if (node_p->u_right) distribute_exp(node_p->u_right,exp_p);
                   1991: }
                   1992: 
                   1993: /* ---------------------------------------------------------------
                   1994:    B.term  := U.item
                   1995:            | N.item
                   1996:            | '(' B.block ')'
                   1997:            | '{' B.block '}'
                   1998:            
                   1999:            | '(' B.block ')' '^' N.term  <== July 6 1998
                   2000:            | '{' B.block '}' '^' N.term
                   2001:            
                   2002:    --------------------------------------------------------------- */
                   2003: Unit_t *
                   2004: scan_basic_term()
                   2005: {
                   2006:   Unit_t   *node_p, *exp_p;
                   2007:   int       ch, nch;
                   2008:   
                   2009:   ch = s_peeknextNW();
                   2010:   if( ch == '(' || ch == '{' ) {
                   2011:     ch = s_getnextNW();  /* get rid of '(' or '{' */
                   2012:     node_p = scan_basic_block();
                   2013:     nch = s_peeknextNW();
                   2014:     if( nch == ')' || nch == '}' ) {  /* should be either ')' or '}' */
                   2015:       if( ((ch == '(' ) && (nch == ')' )) ||
                   2016:           ((ch == '{' ) && (nch == '}' )) ) { /* matching left paren with right paren */
                   2017:           
                   2018:            
                   2019:       } else {
                   2020:         /* printf(" WARN: %c matched by %c\n", ch, nch); */
                   2021:       }
                   2022:       nch = s_getnextNW();
                   2023:       /* ====== Added Jul 6, 1998 ====> */
                   2024:       ch = s_peeknext_op();
                   2025:       if( ch == '^' ) {
                   2026:         ch = s_getnext_op();  /* get rid of '^' char */
                   2027:         exp_p = scan_num_term();
                   2028: 	distribute_exp(node_p,exp_p);
                   2029:         capa_mfree((char *)exp_p);
                   2030:       } 
                   2031:       /* <== added Jul 6, 1998 == */
                   2032:     } else {
                   2033:       /* printf(" WARN: %c is not matched by %c\n", ch, nch); */
                   2034:     }
                   2035:   } else if( ch >= '0' && ch <= '9' ) {
                   2036:     node_p = scan_num_item();
                   2037:   } else { /* assume a unit symbol */
                   2038:     /* printf("<B.term>"); print_remains(); */
                   2039:     node_p = scan_unit_item();
                   2040:     /* print_remains(); */
                   2041:   }
                   2042:   return node_p;
                   2043: }
                   2044: /* --------------------------------------------------
                   2045:    N.term  := N.item
                   2046:            | '-' N.item
                   2047:            | '(' N.expr ')'
                   2048:            | '{' N.expr '}'
                   2049:  -------------------------------------------------- */
                   2050: Unit_t *
                   2051: scan_num_term()
                   2052: {
                   2053:   Unit_t   *node_p;
                   2054:   char      ch, nch;
                   2055: 
                   2056:   ch = s_peeknextNW();
                   2057:   if( ch == '(' || ch == '{' ) {
                   2058:     ch = s_getnextNW();
                   2059:     node_p = scan_num_expr();
                   2060:     nch = s_peeknextNW();
                   2061:     if( nch == ')' || nch == '}' ) {  /* should be either ')' or '}' */
                   2062:       if( ((ch == '(' ) && (nch == ')' )) ||
                   2063:           ((ch == '{' ) && (nch == '}' )) ) { 
                   2064:         
                   2065:       } else {
                   2066:         /* printf(" WARN: %c matched by %c\n", ch, nch); */
                   2067:       }
                   2068:       nch = s_getnextNW();
                   2069:     } else {
                   2070:       /* printf(" WARN: %c is not matched by %c\n", ch, ch); */
                   2071:     }
                   2072:   } else if( ch == '-' ) {
                   2073:     ch = s_getnextNW();
                   2074:     node_p = scan_num_item();
                   2075:     node_p->u_scale = (-1)*node_p->u_scale;
                   2076:   } else {
                   2077:     if( isdigit(ch) ) {
                   2078:        node_p = scan_num_item();
                   2079:     } else { /* something other than a number */
                   2080:        /*
                   2081:           printf(" ERROR: expect a number: ");
                   2082:           print_remains();
                   2083:        */
                   2084:        node_p = p_new_num(NULL, 0.0, NULL); /* make the unknown item */
                   2085:     }
                   2086:   }
                   2087:   return node_p;
                   2088: }
                   2089: 
                   2090: /* --------------------------------------------------
                   2091:    B.block := B.term
                   2092:            | B.term ' ' B.term
                   2093:            | B.term '*' B.term
                   2094:            | B.term '/' B.term
                   2095:    -------------------------------------------------- */
                   2096: Unit_t  *
                   2097: scan_basic_block()
                   2098: {
                   2099:   Unit_t   *node_p;
                   2100:   char      ch;
                   2101:   int       op;
                   2102:   
                   2103:   /* printf("<B.block>(before B.term)"); print_remains(); */
                   2104:   node_p = scan_basic_term();
                   2105:   ch = s_peeknext_op();
                   2106:   while ( ch == '*' || ch == '/' ) {
                   2107:     op = ( ch == '/' ? U_OP_DIVIDE : U_OP_TIMES);
                   2108:     ch = s_getnext_op();
                   2109:     /* printf("<B.block>(/ *)"); print_remains();  */
                   2110:     node_p = p_new_op(node_p,op,scan_basic_term());
                   2111:     ch = s_peeknext_op();
                   2112:   }
                   2113:   return node_p;
                   2114: }
                   2115: /* --------------------------------------------------
                   2116:    N.block := N.term 
                   2117:            | N.term ' ' N.term
                   2118:            | N.term '*' N.term
                   2119:            | N.term '/' N.term
                   2120:    -------------------------------------------------- */
                   2121: Unit_t  *
                   2122: scan_num_block()
                   2123: {
                   2124:   Unit_t   *node_p, *opand_p;
                   2125:   char      ch;
                   2126:   double    result;
                   2127:   
                   2128:   node_p = scan_num_term();
                   2129:   ch = s_peeknext_op();
                   2130:   while ( ch == '*' || ch == '/' ) {
                   2131:     s_getnext_op();
                   2132:     opand_p = scan_num_term();
                   2133:     if( ch == '*' ) {
                   2134:       result = node_p->u_scale * opand_p->u_scale;
                   2135:     } else {
                   2136:       result = node_p->u_scale / opand_p->u_scale;
                   2137:     }
                   2138:     node_p->u_scale = result;
                   2139:     capa_mfree((char *)opand_p);
                   2140:     ch = s_peeknext_op();
                   2141:   }
                   2142:   return node_p;
                   2143: }
                   2144: 
                   2145: /* ---------------------------------------
                   2146:    U.expr  := B.block
                   2147:            | B.block '+' B.block
                   2148:            | B.block '-' B.block
                   2149:    --------------------------------------- */
                   2150: Unit_t  *
                   2151: scan_unit_expr()
                   2152: {
                   2153:   Unit_t   *node_p;
                   2154:   char      ch;
                   2155:   int       op;
                   2156:   
                   2157:   /* printf("<U.expr>"); print_remains();  */
                   2158:   node_p = scan_basic_block();
                   2159:   ch = s_peeknext_op();
                   2160:   while ( ch == '+' || ch == '-' ) {
                   2161:     op = ( ch == '+' ? U_OP_PLUS : U_OP_MINUS);
                   2162:     ch = s_getnext_op();
                   2163:     /* printf("<U.expr>(+-)"); print_remains(); */
                   2164:     node_p = p_new_op(node_p,op,scan_basic_block());
                   2165:     ch = s_peeknext_op();
                   2166:   }
                   2167:   return node_p;
                   2168: }
                   2169: /* -----------------------------------------
                   2170:    N.expr  := N.block 
                   2171:            | N.block '+' N.block
                   2172:            | N.block '-' N.block
                   2173:    ----------------------------------------- */
                   2174: Unit_t  *
                   2175: scan_num_expr()
                   2176: {
                   2177:   Unit_t   *node_p, *opand_p;
                   2178:   char      ch;
                   2179:   double    result;
                   2180:   
                   2181:   node_p = scan_num_block();
                   2182:   ch = s_peeknext_op();
                   2183:   while ( ch == '+' || ch == '-' ) {
                   2184:     ch = s_getnext_op();
                   2185:     opand_p = scan_num_block();
                   2186:     if( ch == '+' ) {
                   2187:       result = node_p->u_scale + opand_p->u_scale;
                   2188:     } else {
                   2189:       result = node_p->u_scale - opand_p->u_scale;
                   2190:     }
                   2191:     node_p->u_scale = result;
                   2192:     capa_mfree((char *)opand_p);
                   2193:     ch = s_peeknext_op();
                   2194:   }
                   2195:   return node_p;
                   2196: }
                   2197: 
                   2198: /* ----------------------------------------------------------------------- */
                   2199: /* <--  This is the major entry point to parse an units expression ------> */
                   2200: Unit_t  *
                   2201: parse_unit_expr(char *symb_str)
                   2202: {
                   2203:   Unit_t   *root_p;
                   2204:   int       len;
                   2205:   
                   2206:   len = strlen(symb_str);
                   2207:   strcpy(Sbuf,symb_str);  /* copy it into the global Sbuf */
                   2208:   Sidx=0;
                   2209:   root_p = scan_unit_expr();
                   2210:   if(Sidx < len-1 ) {
                   2211:     /* printf(" WARN: NOT PARSED:");  print_remains(); */
                   2212:   }
                   2213:   return (root_p);
                   2214: 
                   2215: }
                   2216: 
                   2217: void
                   2218: print_remains()
                   2219: {
                   2220:   int       len, ii;
                   2221:   
                   2222:   len = strlen(Sbuf);
                   2223:   printf("[[");
                   2224:   for(ii=Sidx;ii<len;ii++) {
                   2225:       printf("%c",Sbuf[ii]);
                   2226:   }
                   2227:   printf("]]");
                   2228:   
                   2229: }
                   2230: 
                   2231: 
                   2232: 
                   2233: /* =================================================================== */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.