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

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>