File:  [LON-CAPA] / capa / capa51 / pProj / capaUnit.c
Revision 1.4: download - view: text, annotated - select for diffs
Wed Mar 22 21:08:03 2000 UTC (24 years, 3 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- Lots of little changes

    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: /* returns 1 on okay, 2 on error*/
  636: int
  637: postwalk_utree(Unit_t  *n_p)
  638: {
  639:   int  result;
  640:   
  641:   if( n_p == NULL )  return (1);
  642:   
  643:   result = postwalk_utree(U_LEFT(n_p));
  644:   if (result !=2) {
  645:     if( result ) result = postwalk_utree(U_RIGHT(n_p));
  646:     if (result !=2) {
  647:       if( result ) {
  648: 	switch(U_TYPE(n_p)) {
  649: 	case U_DERIVED:   Ptopidx++; Pstack[Ptopidx] = n_p;  /* push into stack */
  650: 	  break;
  651: 	case U_CONSTANT:  Ptopidx++; Pstack[Ptopidx] = n_p;  /* push into stack */
  652: 	  break;
  653: 	case U_UNKNOWN:   result=2; 
  654: 	  /*push into stack anyway, try to parse rest of tree */
  655: 	  break;
  656: 	case U_OP_POWER:  printf("^"); result=2;
  657: 	  break;
  658: 	case U_OP_TIMES:  process_op(U_OP_TIMES);        /* process operator */
  659: 	  break;
  660: 	case U_OP_PLUS:   printf("+"); result=2;
  661: 	  break;
  662: 	case U_OP_MINUS:  printf("-"); result=2;
  663: 	  break;
  664: 	case U_OP_DIVIDE: process_op(U_OP_DIVIDE);       /* process operator */
  665: 	  break;
  666: 	default:          printf("()"); result=2;
  667: 	  break;  
  668: 	}
  669:       }
  670:     }
  671:   }
  672:   return (result);
  673: }
  674: 
  675: void
  676: process_op(int op)
  677: {
  678:   Unit_t  *ap, *bp;
  679:   double   exp_scale;
  680:   int      no_error=1;
  681:   
  682:   bp = Pstack[Ptopidx--]; 
  683:   ap = Pstack[Ptopidx--]; 
  684:   
  685:   switch(op) {
  686:     case U_OP_TIMES:  exp_scale = 1.0;  break;
  687:     case U_OP_DIVIDE: exp_scale = -1.0; break;
  688:     case U_OP_PLUS:   
  689:     case U_OP_MINUS:  no_error = u_pm_op(ap,bp,op);
  690:                       if(no_error) {
  691:                         Ptopidx++;
  692:                         Pstack[Ptopidx] = ap;
  693:                       }
  694:                       break;
  695:     default:          no_error=0; 
  696:                       printf("No such op on the parse tree!\n");
  697:           break;
  698:   }
  699:   if(no_error) {
  700:     u_copy_unit(ap, bp, exp_scale);
  701:     Ptopidx++;
  702:     Pstack[Ptopidx] = ap;
  703:   }
  704: }
  705: 
  706: void
  707: process_utree(Unit_t *t)
  708: {
  709:   Ptopidx=0;
  710:   postwalk_utree(t);
  711:   if( Ptopidx == 1 ) {
  712:     /* printf("Correctly parsed!\n"); */
  713:     printf("Unit:%s\n",Sbuf);
  714:     simplify_unit(Pstack[Ptopidx]);
  715:     Pstack[Ptopidx]->u_symbol[0]='\0';
  716:     /*sprintf(Pstack[Ptopidx]->u_symbol,"");*/
  717:     print_unit_t(Pstack[Ptopidx]);
  718:     u_find_name(Pstack[Ptopidx]);
  719:     print_matches(Pstack[Ptopidx]);
  720:     free_utree(t);
  721:   }
  722: }
  723: 
  724: /* ============================================================== */
  725: /*  called from capaCommon.c */
  726: /*                      */
  727: /*  UNIT_FAIL           */
  728: /*  NO_UNIT             */
  729: /*  result: UNIT_OK correct   */
  730: /*                            */
  731: /* -------------------------------------------------------------- */
  732: int  check_correct_unit(char *u_symb,Unit_t *t,double *scale)
  733: {
  734:   Unit_t   *ap;
  735:   int       result=UNIT_OK;
  736: 
  737: #ifdef UNIT_DBUG
  738:    if ((ufp=fopen("unit.DBUG","a"))==NULL) { fprintf(stderr,"Error: can't open login debug\n"); return UNIT_FAIL; }
  739: #endif 
  740: 
  741:   while( isspace(*u_symb) )  u_symb++; 
  742:   /* <= change this to search from the end of string */
  743:   /* or to get rid of all the white spaces */
  744: 
  745: 
  746:   ap = parse_unit_expr(u_symb);
  747:   Ptopidx=0;
  748: 
  749:   if (postwalk_utree(ap)==1) {
  750: #ifdef UNIT_DBUG
  751:     fprintf(ufp,"Ptopidx %d\n",Ptopidx);
  752: #endif
  753:     if( Ptopidx == 1 ) {
  754:       simplify_unit(Pstack[Ptopidx]);
  755:       
  756:       if( (Pstack[Ptopidx]->u_count != 0) ||
  757: 	  (Pstack[Ptopidx]->u_count == t->u_count) ) { /* has unit */
  758: 	*scale = units_ratio(Pstack[Ptopidx], t);
  759: 	if( *scale == 0.0 ) {
  760: 	  result = UNIT_FAIL;
  761: 	}
  762: 	free_utree(ap);
  763:       } else {
  764: 	result = UNIT_FAIL;
  765:       }
  766:     } else { /* invalid unit representation */
  767:       result = UNIT_FAIL;
  768:     }
  769:   } else {
  770:     result = UNIT_FAIL;
  771:   }
  772: #ifdef UNIT_DBUG
  773:   fclose(ufp);
  774: #endif 
  775:   return (result);
  776: }
  777: 
  778: /* ============================================================= */
  779: int
  780: free_units()
  781: {
  782:   free_utree(UnitTree_p);
  783:   UnitTree_p=NULL;
  784:   return 0;
  785: }
  786: 
  787: int
  788: free_utree(Unit_t  *t)
  789: {
  790:   int  result=1;
  791:   
  792:   if( t == NULL )  return (1);
  793:   u_postfree(t);
  794:   t=NULL;
  795:   
  796:   return (result);
  797: }
  798: 
  799: 
  800: int
  801: u_postfree(Unit_t  *t)
  802: {
  803:   int  result;
  804:   
  805:   if( t == NULL )  return (1);
  806:   
  807:   result = u_postfree(U_LEFT(t));
  808:   if( result ) result = u_postfree(U_RIGHT(t));
  809:   if( result ) {
  810:     if( t->u_comment ) {
  811:       capa_mfree((char *)t->u_comment);
  812:     }
  813:     freelist_unit_e(t->u_list);
  814:     capa_mfree((char *)t);
  815:   }
  816:   return (result);
  817: }
  818: 
  819: 
  820: void
  821: print_unit_t(Unit_t *t) 
  822: {
  823:   Unit_E  *ue_p;
  824: 
  825:   /* printf("  Unit::[%s,%d]= %g * ", t->u_symbol,t->u_count,t->u_scale); */
  826:   printf("  Unit::[%s] = %g * ", t->u_symbol, t->u_scale);
  827:   for(ue_p=t->u_list; ue_p ; ue_p = ue_p->ue_nextp) {
  828:     /*
  829:     printf("<%s,%d,%g,%g> ",ue_p->ue_symbol,ue_p->ue_index,ue_p->ue_scale,ue_p->ue_exp);
  830:     */
  831:     printf("(%g*%s^%g) ",ue_p->ue_scale,ue_p->ue_symbol,ue_p->ue_exp);
  832:   }
  833:   printf("\n");
  834: 
  835: }
  836: /*  ----------------------------------------------------------- */
  837: /*  copy the Unit_E linked list from b_p->u_list to a_p->u_list */
  838: /*   create some Unit_E nodes in a_p->u_list if needed and      */
  839: /*   leave b_p->u_list intact                                   */
  840: /*   a_p->u_scale is multiplied by pow(b_p->u_scale,exp_scale)  */
  841: /*  ----------------------------------------------------------- */
  842: void
  843: u_copy_unit(Unit_t *a_p, Unit_t *b_p, double exp_scale) 
  844: {
  845:   Unit_E  *oe_p, *ne_p, *last_p;
  846:   int      ii;
  847:   double   scale;
  848:   
  849:   if( a_p->u_count > 0 ) {
  850:     for(last_p = a_p->u_list; last_p->ue_nextp; last_p = last_p->ue_nextp) {  }
  851:   } else {
  852:     a_p->u_list = last_p = NULL;
  853:   }
  854:   if( b_p->u_count > 0 ) {
  855:     oe_p = b_p->u_list;
  856:     for(ii=0;ii<b_p->u_count;ii++) {
  857:       ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E)); /* *** */
  858:       ne_p->ue_scale = oe_p->ue_scale;
  859:       ne_p->ue_exp   = oe_p->ue_exp * exp_scale;
  860:       ne_p->ue_index = oe_p->ue_index;
  861:       strcpy(ne_p->ue_symbol, oe_p->ue_symbol);
  862:       oe_p = oe_p->ue_nextp;
  863:       if( last_p == NULL ) {
  864:         a_p->u_list = ne_p;
  865:       } else {
  866:         last_p->ue_nextp = ne_p;
  867:       }
  868:       last_p = ne_p;
  869:       a_p->u_count++;
  870:     }
  871:     scale = pow(b_p->u_scale, exp_scale);
  872:     a_p->u_scale = a_p->u_scale * scale;
  873:     /* printf("Found scale=%g=%g\n",a_p->u_scale,b_p->u_scale); */
  874:   } else {  
  875:     if( b_p->u_type == U_BASE ) { 
  876:       /* *b_p is a base unit, so create a one element unit */
  877:       ne_p = (Unit_E *) capa_malloc(1, sizeof(Unit_E));   /* *** */
  878:       ne_p->ue_scale = b_p->u_scale;
  879:       ne_p->ue_exp   = exp_scale;
  880:       ne_p->ue_index = b_p->u_index;
  881:       strcpy(ne_p->ue_symbol, b_p->u_symbol);
  882:       if( last_p == NULL ) {
  883:         a_p->u_list = ne_p;
  884:       } else {
  885:         last_p->ue_nextp = ne_p;
  886:       }
  887:       last_p = ne_p;
  888:       a_p->u_count++;
  889:     } else if( b_p->u_type == U_DERIVED) {
  890:       /* derived units but without any units elements (scalar) */
  891:       /* do nothing, ignore this units  WE REALLY MEAN THIS DON'T DO THE NEXT LINE!*/
  892:       /*a_p->u_count++;*/
  893:     } else if( b_p->u_type == U_CONSTANT ) {
  894:       scale = pow(b_p->u_scale, exp_scale);
  895:       a_p->u_scale = a_p->u_scale * scale;
  896:     } else {
  897:       printf("This node has no u_e list and Type unknown\n");
  898:     }
  899:   }
  900: }
  901: int
  902: u_pm_op(Unit_t *a_p, Unit_t *b_p, int op)
  903: {
  904:   int    result=0;
  905:   
  906:   if( a_p->u_count > 0 || b_p->u_count > 0 ) {
  907:      printf(" cannot add or sub units at this moment\n");
  908:      return  result;
  909:   }
  910:   if( op == U_OP_PLUS ) {
  911:     a_p->u_scale = a_p->u_scale + b_p->u_scale;
  912:   } else {
  913:     a_p->u_scale = a_p->u_scale - b_p->u_scale;
  914:   }
  915:   return 1;
  916: }
  917: 
  918: int
  919: u_parsepower(char *unit_str)
  920: {
  921:   int   exp, ii;
  922:   char  *ch_p, exp_str[16];
  923: 
  924:   ch_p = unit_str;
  925:   while( isspace(*ch_p) ) { ch_p++; }
  926:   ii=0;
  927:   while( isdigit(*ch_p) ) {
  928:     ch_p++;
  929:   }
  930:   while( isspace(*ch_p) ) { ch_p++; }
  931:   if( *ch_p == '^' ) {
  932:     ch_p++;
  933:   }
  934:   while( isspace(*ch_p) ) { ch_p++; }
  935:   if( *ch_p == '{' ) {
  936:     ch_p++;
  937:   }
  938:   while( isspace(*ch_p) ) { ch_p++; }
  939:   ii=0;
  940:   while( isdigit(*ch_p) || *ch_p == '-' || *ch_p == '+' ) {
  941:     exp_str[ii++] = *ch_p;
  942:     ch_p++;
  943:   }
  944:   exp_str[ii]=0;
  945:   sscanf(exp_str,"%d", &exp);
  946:   return (exp);
  947: }
  948: 
  949: /* ------------------------------------------- */
  950: /* scan a number of the form indicated below from the input buffer */
  951: /* 1.234^{2.3} */
  952: /*  1e */
  953: double
  954: s_scan_number(char *buf, int idx, int *r_idx)
  955: {
  956:   double   num; 
  957:   float    exp; 
  958:   double   result;
  959:   int      ii=0;
  960:   char     num_str[QUARTER_K];
  961:   
  962:   num_str[ii]=0;
  963:   
  964:   if( buf[idx] == '-' ) {
  965:     num_str[ii++] = '-';
  966:     idx++;
  967:   }
  968:   while( isdigit(buf[idx]) || buf[idx] == '.' ) { 
  969:       num_str[ii++] = buf[idx];
  970:       idx++;
  971:   }
  972:   if( buf[idx] == 'E' || buf[idx] == 'e' ) {
  973:     if( buf[idx+1] == '-' || isdigit(buf[idx+1]) ) {
  974:       num_str[ii++] = buf[idx++];
  975:       num_str[ii++] = buf[idx++];
  976:       while( isdigit(buf[idx]) ) {
  977:         num_str[ii++] = buf[idx];
  978:         idx++;
  979:       }
  980:     }
  981:   }
  982:   num_str[ii] = 0; /* terminate the str */
  983:   sscanf(num_str,"%lg", &num);
  984:   /* printf("Scan number %s got %g\n",num_str, num); fflush(stdout); */
  985:   result = num;
  986:   if( buf[idx] == '^' ) {
  987:     idx++;
  988:     while( isspace(buf[idx]) ) { idx++; }
  989:     if( buf[idx] == '{' ) {  /* need to scan for a matching right bracket */
  990:         idx++;
  991:     }
  992:     while( isspace(buf[idx]) ) { idx++; }
  993:     num_str[0]=0;
  994:     if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' )  {
  995:        ii=0;
  996:        while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
  997:          num_str[ii++] = buf[idx];
  998:          idx++;
  999:        }
 1000:        num_str[ii]=0;
 1001:     }
 1002:     while( isspace(buf[idx]) ) { idx++; }
 1003:     if( buf[idx] == '}' ) {
 1004:       idx++;
 1005:     }
 1006:     sscanf(num_str,"%f", &exp);
 1007:     /* printf("Scan exp number %s got %g\n",num_str, exp); fflush(stdout); */
 1008:     
 1009:     result = pow(num, (double)exp);
 1010:     /* printf("{%d^%d}=%g\n",num, exp,result); */
 1011:   }
 1012:   *r_idx = idx;
 1013:   return (result);
 1014: }
 1015: 
 1016: 
 1017: double
 1018: s_scan_symbol(char *buf,char *symb_p,int idx, int *r_idx)
 1019: {
 1020:   char     num_str[QUARTER_K];
 1021:   int      ii=0;
 1022:   double   r_exp=1.0;
 1023:   
 1024:   symb_p[0]=0;
 1025:   while( isalnum(buf[idx]) || buf[idx] == '_' ) {
 1026:     symb_p[ii++] = buf[idx];
 1027:     idx++;
 1028:   }
 1029:   symb_p[ii]=0;
 1030:   
 1031:   if( buf[idx] == '^' ) {  /* look for either left bracket or a number */
 1032:     idx++;
 1033:     while( isspace(buf[idx]) ) { idx++; } 
 1034:     if( buf[idx] == '{' ) {  /* need to scan for a matching right bracket */
 1035:       idx++;
 1036:     }
 1037:     while( isspace(buf[idx]) ) { idx++; }
 1038:     if( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-'  )  {
 1039:       ii=0; num_str[ii] = 0;
 1040:       while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
 1041:         num_str[ii++] = buf[idx];
 1042:         idx++;
 1043:       }
 1044:       num_str[ii]=0;
 1045:     }
 1046:     while( isspace(buf[idx]) ) { idx++; }
 1047:     if( buf[idx] == '}' ) {
 1048:       idx++;
 1049:     }
 1050:     sscanf(num_str,"%lg", &r_exp);  /* power could be of type float */
 1051:     /* printf("[scan symb with power %s ^ %lg] ",symb_p, r_exp); fflush(stdout);  */
 1052:   }
 1053:   *r_idx = idx;
 1054:   return (r_exp);
 1055: }
 1056: 
 1057: /*  return: err_code    0    parsed ok */
 1058: /*                      1    symbol is of length 1, not found in the tree */
 1059: /*                      2    symbol not found in the tree  */
 1060: /*                      3    symbol parsed as prefix symb, but symb not found */
 1061: /*                      4    symbol length is 0 or negative */
 1062: int
 1063: s_process_symb(char *symb_str,Unit_t  *cu_p,double exp)
 1064: {
 1065:   int      len;
 1066:   Unit_t  *au_p;
 1067:   int      c_result;
 1068:   int      ii;
 1069:   char     tmp_str[ANSWER_STRING_LENG];
 1070:   int      err_code = 0;
 1071:   double   d_exp;
 1072:   
 1073:   len = strlen(symb_str);
 1074:   if( len > 0 ) {
 1075:     au_p = u_find_symb(symb_str, UnitTree_p, &c_result);
 1076:     if( c_result == 1 ) {  /* if found, copy the definition over */
 1077:       u_copy_unit(cu_p, au_p, exp);
 1078:     } else {
 1079:       if( len > 1 ) {
 1080:         if( PrefixTbl[ (int)symb_str[0] ] != 0 ) {  /* prefix is defined */
 1081:           for(ii=1;ii<len;ii++) {
 1082:              tmp_str[ii-1] = symb_str[ii];
 1083:           }
 1084:           tmp_str[len-1]=0;
 1085:           au_p = u_find_symb(tmp_str, UnitTree_p, &c_result);
 1086:           if( c_result == 1 ) {
 1087:               /* printf("[%s] ", tmp_str); */
 1088:             u_copy_unit(cu_p, au_p, exp);
 1089:             d_exp = (double)PrefixTbl[ (int)symb_str[0] ] * exp;
 1090:             cu_p->u_scale = cu_p->u_scale * pow((double)10.0,d_exp);
 1091:           } else { /* unit *tmp_str not found */
 1092:             /*printf("The unit: %s, not defined\n",tmp_str);*/
 1093:             err_code = 3;
 1094:           }
 1095:         } else {
 1096:           /*printf("<<%s>>", symb_str);*/
 1097:           err_code = 2;
 1098:         }
 1099:       } else {/* len == 1 */
 1100: 	/*printf("The unit: %s, not defined\n",symb_str);*/
 1101:         err_code = 1;
 1102:       }
 1103:     }
 1104:   } else {
 1105:     err_code = 4;
 1106:   }
 1107:   return (err_code);
 1108: }
 1109: 
 1110: Unit_t *
 1111: u_parse_unit(char *unit_str)
 1112: {
 1113:   char      *ch;
 1114:   char       symb_str[QUARTER_K];
 1115:   int        idx;
 1116:   double     exp_sign;
 1117:   int        s_result;
 1118:   int        not_done;
 1119:   double     s_number,  offset;
 1120:   double     tmp_scale, symb_exp, exp;
 1121:   Unit_t    *cu_p;
 1122: 
 1123:   gUnitError=0;
 1124:   ch   = unit_str;
 1125:   cu_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t)); /* *** */
 1126:   cu_p->u_scale = 1.0;
 1127:   idx = 0;  not_done = 1;
 1128:   exp_sign = 1.0; exp = 1;
 1129:   symb_str[0] = 0;
 1130: 
 1131:   while( isspace(*ch) ) { ch++; }    /* trim leading white spaces */
 1132:   /* fprintf(stdout,"PARSE |%s|\n", unit_str); */
 1133:   while( not_done ) {
 1134:     if( isdigit(ch[idx]) || ch[idx] == '-' ) {  /* rule 1: number */
 1135:        s_number = s_scan_number(ch,idx,&idx);
 1136:        
 1137:        tmp_scale = pow(s_number,exp_sign);
 1138:        /* printf("S=%g,Power(%g,%d)=%g\n", 
 1139:           cu_p->u_scale, s_number,exp_sign, tmp_scale);
 1140:        */
 1141:        cu_p->u_scale = cu_p->u_scale * tmp_scale;
 1142:        
 1143:        /* printf("[Scale %g=%g^%g] ",tmp_scale,s_number,exp_sign); */
 1144:        while( isspace(ch[idx]) ) { idx++; }
 1145:     } else {
 1146:       if( isalpha(ch[idx]) ) { /* rule 2: unit_symbol ^ exp */
 1147: 	symb_str[0] = 0;
 1148: 	symb_exp = s_scan_symbol(ch,symb_str,idx,&idx);
 1149: 	exp = (double)exp_sign * symb_exp;
 1150: 	/* printf("[scanned %s ^ (%g * %g)] ", symb_str,symb_exp,exp_sign); fflush(stdout); */
 1151: 	s_result = s_process_symb(symb_str,cu_p,exp);
 1152: 	if( s_result > 0 ) {
 1153: 	  /* printf("Error processing symbol [%s]\n", symb_str); */
 1154: 	  gUnitError = 1;
 1155: 	}
 1156: 	while( isspace(ch[idx]) ) { idx++; }
 1157:       } else {
 1158: 	if( ch[idx] == '*' || ch[idx] == '/' ) {
 1159: 	  if( ch[idx] == '/' ) { /* printf("[/] "); */ exp_sign = -1.0; }
 1160: 	  idx++;
 1161: 	  while( isspace(ch[idx]) ) { idx++; }
 1162: 	} else {
 1163: 	  if( ch[idx] == '+' || ch[idx] == '-' ) {
 1164: 	    idx++;
 1165: 	    while( isspace(ch[idx]) ) { idx++; }
 1166: 	    offset = s_scan_number(ch,idx,&idx);
 1167: 	    /* printf("[Offset %g] ",offset); */
 1168: 	  } else {
 1169: 	    if( ch[idx] == 0 ) {  /* end of input string */
 1170: 	      not_done = 0;
 1171: 	      /* printf("\n"); */
 1172: 	    } else {
 1173: 	      /* garbage in unit string */
 1174: 	      gUnitError = 1;
 1175: 	      not_done=0;
 1176: 	    }
 1177: 	  }
 1178: 	}
 1179:       }
 1180:     }
 1181:   }
 1182:   simplify_unit(cu_p);
 1183:   return (cu_p);
 1184: 
 1185: }
 1186: 
 1187: void
 1188: u_getunit(FILE *f)
 1189: {
 1190:   register int  unit_type;
 1191:   register int  c;
 1192:   int      power, result;
 1193:   char   *name_p, *symbol_p, *comment_p, *unit_p;
 1194:   
 1195:   BaseUnitcnt = 0;
 1196:   free_utree(UnitTree_p);
 1197:   UnitTree_p = NULL;
 1198:   c_moveto_unit(f);  /* move the file position to << */
 1199:   do {
 1200:     c_ignorewhite(f);
 1201:     c = getc(f); ungetc(c,f);
 1202:     if( c == '<' ) {
 1203:       unit_type = c_gettype(f);
 1204:     }
 1205:     if( c != EOF ) {
 1206:       switch(unit_type) {
 1207:         case U_BASE:
 1208:                name_p    = c_getword(f);    symbol_p = c_getword(f); 
 1209:                comment_p = c_getcomment(f);
 1210:                /*
 1211:                printf("B Unit: N=%s,S=%s,C=%s\n",name_p,symbol_p,comment_p);
 1212:                */
 1213:                result = u_insert_baseunit(name_p,symbol_p,comment_p);
 1214:                if( result == 1 ) {
 1215:                  printf("The entry %s is duplicated\n",symbol_p);
 1216:                }
 1217:                free(name_p); free(symbol_p); free(comment_p);
 1218:                break;
 1219:         case U_DERIVED:
 1220:                name_p    = c_getword(f);    symbol_p = c_getword(f);
 1221:                unit_p    = c_getstring(f);  comment_p = c_getcomment(f);
 1222:                /*
 1223:                printf("D Unit: N=%s,S=%s,C=%s,U=%s\n",
 1224:                        name_p,symbol_p,comment_p,unit_p);
 1225:                */
 1226:                result = u_insert_derived(name_p,symbol_p,comment_p,unit_p);
 1227:                if( result == 1 ) {
 1228:                  printf("The entry %s is duplicated\n",symbol_p);
 1229:                }
 1230:                /* preorder_utree(UnitTree_p); */ 
 1231:                free(name_p); free(symbol_p); free(comment_p); free(unit_p);
 1232:                break;
 1233:         case U_PREFIX:
 1234:                name_p    = c_getword(f);    symbol_p = c_getword(f);
 1235:                unit_p    = c_getstring(f);
 1236:                /*
 1237:                printf("Prefix: N=%s,S=%s,U=%s\n",
 1238:                        name_p,symbol_p,unit_p);
 1239:                */
 1240:                power = u_parsepower(unit_p);
 1241:                PrefixTbl[ (int)(*symbol_p) ] = power;
 1242:                /* printf("    P[%c]=%d\n",*symbol_p,power);  */
 1243:                free(name_p); free(symbol_p); free(unit_p);
 1244:                break;
 1245:         case U_CONSTANT:
 1246:                symbol_p = c_getword(f);  unit_p    = c_getstring(f);
 1247:                comment_p = c_getcomment(f);
 1248:                /*
 1249:                printf("Const.: S=%s,C=%s,U=%s\n",
 1250:                        symbol_p,comment_p,unit_p);
 1251:                */
 1252:                break;
 1253:         case U_UNKNOWN:
 1254:                /* printf("Unknown\n"); */
 1255:                break;
 1256:       }
 1257:     }
 1258:   } while ( c != EOF );
 1259: 
 1260: }
 1261: 
 1262: /* ----------------------------------------------------------------- */
 1263: /* comparing unit symbol names should be case sensitive */
 1264: int
 1265: comp_unit_symb(a, b) char *a; char *b;
 1266: {
 1267:   return strncmp(a,b,SYMBOL_MAXLEN);
 1268: }
 1269: 
 1270: 
 1271: Unit_t *
 1272: u_splay (char *name, Unit_t *t) 
 1273: {
 1274:   Unit_t     N;
 1275:   Unit_t    *l, *r, *y;
 1276: 
 1277:   if (t == NULL)  return t;
 1278:   N.u_left  = (Unit_t *)NULL;
 1279:   N.u_right = (Unit_t *)NULL;
 1280:   l = r = &N;
 1281: 
 1282:   for (;;) {
 1283:     if ( comp_unit_symb(name,t->u_symbol) < 0 ) {
 1284:       if (t->u_left == NULL)  break;
 1285:       if ( comp_unit_symb(name, (t->u_left)->u_symbol ) < 0 ) {
 1286:         y = t->u_left; t->u_left = y->u_right; y->u_right = t; t = y;
 1287:         if (t->u_left == NULL) break;
 1288:       }
 1289:       r->u_left = t; r = t; t = t->u_left;
 1290:     } else if ( comp_unit_symb(name,t->u_symbol) > 0 ) {
 1291:         if (t->u_right == NULL) break;
 1292:         if ( comp_unit_symb(name, (t->u_right)->u_symbol ) > 0 ) {
 1293:           y = t->u_right; t->u_right = y->u_left; y->u_left = t; t = y;
 1294:           if (t->u_right == NULL) break;
 1295:         }
 1296:         l->u_right = t; l = t; t = t->u_right;
 1297:     } else {
 1298:       break;
 1299:     }
 1300:   }
 1301:   l->u_right = t->u_left; r->u_left = t->u_right; t->u_left = N.u_right;
 1302:   t->u_right = N.u_left;
 1303:   return t;
 1304: }
 1305: 
 1306: 
 1307: 
 1308: /* returns: 0  correctly inserted */
 1309: /*          -1 error */
 1310: /*          1  duplicate entry    */
 1311: 
 1312: int
 1313: u_insert_baseunit(n_p,s_p,c_p) char  *n_p, *s_p, *c_p;
 1314: {
 1315:   Unit_t   *new_p, *t;
 1316:   int       len;
 1317:  
 1318:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t)); /* *** */
 1319:   if (new_p == NULL) {
 1320:       printf("Ran out of space\n");
 1321:       return(-1);
 1322:   }
 1323:   strcpy(new_p->u_symbol, s_p);
 1324:   strcpy(new_p->u_name, n_p);
 1325:   len = strlen(c_p);
 1326:   new_p->u_comment = (char *) capa_malloc((len+1), sizeof(char)); /* *** */
 1327:   strcpy(new_p->u_comment,c_p);
 1328:   BaseUnitcnt++;
 1329:   new_p->u_index  = BaseUnitcnt;
 1330:   new_p->u_type   = U_BASE;
 1331:   new_p->u_scale  = 1.0;
 1332:   new_p->u_offset = 0.0;
 1333:   new_p->u_count  = 0;
 1334:   new_p->u_list   = NULL;
 1335:  
 1336:   if (UnitTree_p == NULL) {  /* a new unit tree */
 1337:       UnitTree_p = new_p;
 1338:       return (0);
 1339:   }
 1340:   t = u_splay(s_p, UnitTree_p);
 1341:   if ( comp_unit_symb(s_p,t->u_symbol) < 0 ) {
 1342:         new_p->u_left = t->u_left; new_p->u_right = t;
 1343:         t->u_left = NULL;
 1344:         /* Splay_cnt++;  */
 1345:         UnitTree_p = new_p;
 1346:         return (0);
 1347:   } else if ( comp_unit_symb(s_p,t->u_symbol) > 0 ) {
 1348:         new_p->u_right = t->u_right; new_p->u_left = t;
 1349:         t->u_right = NULL;
 1350:         /* Splay_cnt++; */
 1351:         UnitTree_p = new_p;
 1352:         return (0);
 1353:   } else {    /* name and t->u_symbol is the same, which means found it */
 1354:         capa_mfree( (char *)new_p );
 1355:         UnitTree_p = t;
 1356:         return (1);
 1357:   }
 1358: }
 1359: 
 1360: 
 1361: int
 1362: u_insert_derived(n_p,s_p,c_p,u_p)char  *n_p, *s_p, *c_p, *u_p;
 1363: {
 1364:   Unit_t  *new_p, *t;
 1365:   int      c_result, len;
 1366:   
 1367:   /* inorder_utree(UnitTree_p); */
 1368:   t = u_splay(s_p, UnitTree_p);
 1369:   UnitTree_p = t;
 1370:   c_result = comp_unit_symb(s_p,t->u_symbol);
 1371:   if ( c_result == 0 ) {
 1372:     UnitTree_p = t;
 1373:     return (1);
 1374:   }
 1375:   
 1376:   /* prepare a new Unit_t */
 1377:   new_p = u_parse_unit(u_p);
 1378:   strcpy(new_p->u_symbol,s_p);
 1379:   strcpy(new_p->u_name, n_p);
 1380:   new_p->u_type = U_DERIVED;
 1381:   len = strlen(c_p);
 1382:   new_p->u_comment = (char *) capa_malloc((len+1), sizeof(char)); /* *** */
 1383:   strcpy(new_p->u_comment,c_p);
 1384:   
 1385:   simplify_unit(new_p);
 1386:   /*
 1387:   printf("Derived Unit:%s\n",new_p->u_name);
 1388:   print_unit_t(new_p); 
 1389:   */
 1390:   if (c_result < 0 ) {
 1391:     new_p->u_left = t->u_left; new_p->u_right = t;
 1392:     t->u_left = NULL;
 1393:   } else {  /* c_result > 0 */
 1394:     new_p->u_right = t->u_right; new_p->u_left = t;
 1395:     t->u_right = NULL;
 1396:   }
 1397:   UnitTree_p = new_p;
 1398:   
 1399:   return (0);
 1400:   
 1401: }
 1402: 
 1403: void
 1404: freelist_unit_e(Unit_E *ue_p) 
 1405: {
 1406:   Unit_E  *curr_p, *next_p;
 1407:   
 1408:   if( ue_p != NULL ) {
 1409:     next_p = ue_p->ue_nextp;
 1410:     curr_p = ue_p;
 1411:     if( next_p == NULL ) {
 1412:       capa_mfree((char *)curr_p);
 1413:     } else {
 1414:       for( curr_p = ue_p; next_p; curr_p = next_p, next_p = next_p->ue_nextp) {
 1415:         capa_mfree((char *)curr_p);
 1416:       }
 1417:       capa_mfree((char *)curr_p);
 1418:     }
 1419:   }
 1420: }
 1421: void
 1422: simplify_unit(u_p) Unit_t *u_p;
 1423: {
 1424:   Unit_E   *eu_p, *prev_p;
 1425:   int       ii, idx;
 1426:   
 1427:   /* walk through u_list and replace those u_index = -1 with */
 1428:   /* a linked list of basic unit. */
 1429:   /* u_msort_main() the whole u_list */
 1430:   /* combine those units with same u_index */
 1431:   for(ii=0;ii<BaseUnitcnt;ii++) {
 1432:     CScale[ii] = 0.0;
 1433:     CExp[ii] = 0.0;
 1434:   }
 1435:   /*
 1436:   printf("Before Simplify:: \n");
 1437:   print_unit_t(u_p);
 1438:   */
 1439:   if( u_p->u_count > 0 ) {
 1440:     
 1441:     for(eu_p=u_p->u_list; eu_p; eu_p = eu_p->ue_nextp) {
 1442:       idx = eu_p->ue_index;
 1443:       if( CScale[idx] == 0.0 ) {
 1444:         CScale[idx] = 1.0;
 1445:         strcpy(CSymb[idx],eu_p->ue_symbol);
 1446:       }
 1447:       CScale[idx] = CScale[idx] * eu_p->ue_scale;
 1448:       CExp[idx] = CExp[idx] + eu_p->ue_exp;
 1449:     }
 1450:     /* debugging 
 1451:     for(ii=0;ii<BaseUnitcnt;ii++) {
 1452:       if( CScale[ii] != 0.0 ) {
 1453:         printf("(%d)%s,S=%g,E=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]);
 1454:       }
 1455:       if( CExp[ii] == 0.0 ) {
 1456:         printf("(%d)%s,S=%g,Exp=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]);
 1457:       }
 1458:     }
 1459:     */
 1460:     freelist_unit_e(u_p->u_list);
 1461:     prev_p = u_p->u_list = NULL;
 1462:     u_p->u_count = 0;
 1463:     for(ii=0;ii<BaseUnitcnt;ii++) {
 1464:       if( CScale[ii] != 0.0 && CExp[ii] != 0) {
 1465:         eu_p = (Unit_E *)capa_malloc(1,sizeof(Unit_E)); /* ***************** */
 1466:         eu_p->ue_scale = 1.0;
 1467:         eu_p->ue_exp = CExp[ii];
 1468:         eu_p->ue_index = ii;
 1469:         strcpy(eu_p->ue_symbol,CSymb[ii]);
 1470:         if( prev_p == NULL) {
 1471:           u_p->u_list = prev_p = eu_p;
 1472:         } else {
 1473:           prev_p->ue_nextp = eu_p;
 1474:           prev_p = eu_p;
 1475:         }
 1476:         u_p->u_count++;
 1477:       }
 1478:     }
 1479:   }
 1480:   /* 
 1481:   printf("After Simplify:: \n");
 1482:   print_unit_t(u_p);
 1483:   */
 1484: }
 1485: 
 1486: /* before comparing two units, make sure they are of  basic form */
 1487: /* compares if two units are equal */
 1488: /* equality returns 1 */
 1489: 
 1490: int  is_units_equal(Unit_t *u1_p, Unit_t *u2_p)
 1491: {
 1492:   int      result=1;
 1493:   Unit_E  *a_p, *b_p;
 1494:   
 1495:   if( (u1_p->u_count == u2_p->u_count) && 
 1496:       (u1_p->u_scale == u2_p->u_scale) ) {
 1497:     for(a_p=u1_p->u_list, b_p=u2_p->u_list;
 1498:         a_p; a_p=a_p->ue_nextp, b_p=b_p->ue_nextp) {
 1499:       if(a_p->ue_index != b_p->ue_index ||
 1500:          a_p->ue_scale != b_p->ue_scale ||
 1501:          a_p->ue_exp   != b_p->ue_exp ) {
 1502:         result=0;
 1503:         break;
 1504:       }
 1505:     }
 1506:   } else {
 1507:     result=0;
 1508:   }
 1509:   return (result);
 1510: }
 1511: /*     input : both are the simplest units */
 1512: /*     result: 0.0 means they are not of euquvalent units */
 1513: /*             the ratio of u1 / u2   */
 1514: double  units_ratio(Unit_t *u1_p, Unit_t *u2_p)
 1515: {
 1516:   double   ratio=1.0;
 1517:   Unit_E  *a_p, *b_p;
 1518:   
 1519:   if( (u1_p->u_count == u2_p->u_count) ) {
 1520:     for(a_p=u1_p->u_list, b_p=u2_p->u_list;
 1521:         a_p; a_p=a_p->ue_nextp, b_p=b_p->ue_nextp) {
 1522:       if(a_p->ue_index != b_p->ue_index ||
 1523:          a_p->ue_scale != b_p->ue_scale ||
 1524:          a_p->ue_exp   != b_p->ue_exp ) {
 1525:         ratio=0.0;
 1526:         break;
 1527:       }
 1528:     }
 1529:   } else {
 1530:     ratio=0.0;
 1531:   }
 1532:   if( (ratio != 0.0) && (u2_p->u_scale != 0.0 )  ) {
 1533:     ratio = u1_p->u_scale / u2_p->u_scale;
 1534:   }
 1535:   return (ratio);
 1536: }
 1537: 
 1538: /* ------------- The Grammar of Units Parser --------------------
 1539: 
 1540:   scan_unit_expr()  -->  scan_basic_block()
 1541:                     -->  scan_basic_block() '+' scan_basic_block() 
 1542:                     -->  scan_basic_block() '-' scan_basic_block()
 1543:  
 1544:   scan_num_expr()   -->  scan_num_block()
 1545:                     -->  scan_num_block() '+' scan_num_block()
 1546:                     -->  scan_num_block() '-' scan_num_block()
 1547:                     
 1548:   scan_basic_block()-->  scan_basic_term()
 1549:                     -->  scan_basic_term()  '*' scan_basic_term()
 1550:                     -->  scan_basic_term()  ' ' scan_basic_term()
 1551:                     -->  scan_basic_term()  '/' scan_basic_term()
 1552: 
 1553:   scan_num_block()  -->  scan_num_term()
 1554:                     -->  scan_num_term()  '*' scan_num_term()
 1555:                     -->  scan_num_term()  ' ' scan_num_term()
 1556:                     -->  scan_num_term()  '/' scan_num_term()
 1557:   
 1558:   
 1559:   scan_basic_term() -->  scan_unit_item()          
 1560:                     -->  scan_num_item()
 1561:                     -->  '(' scan_basic_block() ')'
 1562:                     -->  '{' scan_basic_block() '}'
 1563: 
 1564:   scan_num_term()   -->  scan_num_item()<sp>*
 1565:                     --> '-' scan_num_item()<sp>*
 1566:                     --> '(' scan_num_expr() ')'
 1567:                     --> '{' scan_num_expr() '}'
 1568: 
 1569:   scan_unit_item()  -->  UNIT<sp>*
 1570:                     -->  UNIT<sp>*  '^' <sp>* scan_num_term()
 1571:                     
 1572:   scan_num_item()   -->  FLOAT<sp>*
 1573:                     -->  FLOAT<sp>* '^' <sp>* scan_num_term()
 1574:   
 1575:   scan_FLOAT()      -->  [0-9]+([eE][+-]?[0-9]+)*
 1576:   
 1577:   p_new_unit()      -->  [a-Z]+[a-Z0-9_]*
 1578:   
 1579:   -----------------------------------------
 1580:   U.expr  := B.block
 1581:            | B.block '+' B.block
 1582:            | B.block '-' B.block
 1583:            
 1584:   N.expr  := N.block 
 1585:            | N.block '+' N.block
 1586:            | N.block '-' N.block
 1587:  
 1588:  To allow for operations like (J/N)^2 or {N/m}^2 (N/J)^3 
 1589:  
 1590:  
 1591:   B.block := B.term
 1592:            | B.term ' ' B.term
 1593:            | B.term '*' B.term
 1594:            | B.term '/' B.term
 1595:            
 1596:   N.block := N.term 
 1597:            | N.term ' ' N.term
 1598:            | N.term '*' N.term
 1599:            | N.term '/' N.term
 1600:            
 1601:   B.term  := U.item
 1602:            | N.item
 1603:            | '(' B.block ')'
 1604:            | '{' B.block '}'
 1605:            
 1606:            | '(' B.block ')' ^ N.term
 1607:            | '{' B.block '}' ^ N.term
 1608:            
 1609:   N.term  := N.item
 1610:            | '-' N.item
 1611:            | '(' N.expr ')'
 1612:            | '{' N.expr '}'
 1613:            
 1614:   U.item  := UNIT
 1615:            | UNIT '^' N.term
 1616:            
 1617:   N.item  := FLOAT
 1618:            | FLOAT '^' N.term
 1619:            
 1620:   UNIT    := [a-Z]+[a-Z0-9_]*
 1621:   
 1622:   FLOAT   := [0-9]+([eE][+-]?[0-9]+)*
 1623:   
 1624:  ------------------------------------------------------------------- */
 1625:  
 1626: Unit_t *
 1627: p_new_op(Unit_t *left_p, int op, Unit_t *right_p)
 1628: {
 1629:   Unit_t  *new_p;
 1630:   
 1631:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
 1632:   if (new_p == NULL) {
 1633:       printf("Ran out of space\n");
 1634:       return(NULL);
 1635:   }
 1636:   new_p->u_left   = left_p;
 1637:   new_p->u_right  = right_p;
 1638:   new_p->u_scale  = 0.0;
 1639:   new_p->u_type   = op;
 1640:   new_p->u_offset = 0.0;
 1641:   new_p->u_count  = 0;
 1642:   new_p->u_list   = NULL;
 1643:   
 1644:   return (new_p);
 1645: }
 1646: 
 1647: Unit_t *
 1648: p_new_num(Unit_t *left_p, double num, Unit_t *right_p)
 1649: {
 1650:   Unit_t  *new_p;
 1651:   
 1652:   new_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
 1653:   if (new_p == NULL) {
 1654:       printf("Ran out of space\n");
 1655:       return(NULL);
 1656:   }
 1657:   
 1658:   new_p->u_left   = left_p;
 1659:   new_p->u_right  = right_p;
 1660:   new_p->u_scale  = num;
 1661:   new_p->u_type   = U_CONSTANT;
 1662:   new_p->u_offset = 0.0;
 1663:   new_p->u_count  = 0;
 1664:   new_p->u_list   = NULL;
 1665:   
 1666:   return (new_p);
 1667: }
 1668: 
 1669: Unit_t *
 1670: p_new_unit(Unit_t *left_p, Unit_t *right_p)
 1671: {
 1672:   char     symb_str[ANSWER_STRING_LENG];
 1673:   int      ii=0;
 1674:   int      len;
 1675:   Unit_t  *au_p, *cu_p;
 1676:   int      c_result;
 1677:   char     tmp_str[ANSWER_STRING_LENG];
 1678:   int      err_code = 0;
 1679:   double   d_exp;
 1680:   
 1681:   symb_str[ii]=0;
 1682:   while( isspace(Sbuf[Sidx]) ) { Sidx++; }
 1683:   while( isalnum(Sbuf[Sidx]) || Sbuf[Sidx] == '_' ) {
 1684:     symb_str[ii++] = Sbuf[Sidx];
 1685:     Sidx++;
 1686:   }
 1687:   symb_str[ii]=0;
 1688:   /* printf("<U %s>", symb_str); */
 1689:   cu_p = (Unit_t *) capa_malloc(1, sizeof(Unit_t));
 1690:   strcpy(cu_p->u_symbol,symb_str);
 1691:   cu_p->u_left   = left_p;
 1692:   cu_p->u_right  = right_p;
 1693:   cu_p->u_scale  = 1.0;
 1694:   cu_p->u_type   = U_DERIVED;
 1695:   cu_p->u_offset = 0.0;
 1696:   cu_p->u_count  = 0;
 1697:   cu_p->u_list   = NULL;
 1698:   
 1699:   len = strlen(symb_str);
 1700:   if( len > 0 ) {
 1701:     au_p = u_find_symb(symb_str, UnitTree_p, &c_result);
 1702:     if( c_result == 1 ) {  /* if found, copy the definition over */
 1703:       u_copy_unit(cu_p, au_p, 1);
 1704:     } else {
 1705:       if( len > 1 ) {
 1706:         if( PrefixTbl[ (int)symb_str[0] ] != 0 ) {  /* prefix is defined */
 1707:           for(ii=1;ii<len;ii++) {
 1708:              tmp_str[ii-1] = symb_str[ii];
 1709:           }
 1710:           tmp_str[len-1]=0;
 1711:           au_p = u_find_symb(tmp_str, UnitTree_p, &c_result);
 1712:           if( c_result == 1 ) {
 1713:               /* printf("[%s] ", tmp_str); */
 1714:             u_copy_unit(cu_p, au_p, 1);
 1715:             d_exp = (double)PrefixTbl[ (int)symb_str[0] ];
 1716:             cu_p->u_scale = cu_p->u_scale * pow((double)10.0,d_exp);
 1717:           } else { /* unit *tmp_str not found */
 1718:             /* printf(" not found\n"); */
 1719:             err_code = 3;
 1720: 	    cu_p->u_type   = U_UNKNOWN;
 1721:           }
 1722:         } else {
 1723:           /* printf("<<%s>>", symb_str); */
 1724:           err_code = 2;
 1725: 	  cu_p->u_type   = U_UNKNOWN;
 1726:         }
 1727:       } else {/* len == 1 */
 1728:         /* printf(" not found\n"); */
 1729:         err_code = 1;
 1730: 	cu_p->u_type   = U_UNKNOWN;
 1731:       }
 1732:     }
 1733:   } else {
 1734:     err_code = 4;
 1735:   }
 1736:   
 1737:   return (cu_p);
 1738: }
 1739: 
 1740: int  s_peeknext_op()
 1741: {
 1742:   char  *ch;
 1743:   int    sp=0;
 1744:   
 1745:   ch = (char *)&Sbuf[Sidx];
 1746:   while( isspace(*ch) ) { ch++; sp=1; }
 1747:   if( (*ch == '*')  || (*ch == '/') || (*ch == '+')  || (*ch == '-') || (*ch == '^')) {
 1748:     return (*ch);
 1749:   }
 1750:   /* what if space is the last thing on the line?*/
 1751:   if( sp && (*ch != '\0')) return '*';
 1752:   return (*ch);
 1753: }
 1754: 
 1755: int  s_getnext_op()
 1756: {
 1757:   char  *ch;
 1758:   int    inc = 0, sp=0;
 1759:   
 1760:   
 1761:   /* printf("\n((op"); print_remains(); printf("\n");  */
 1762:   ch = (char *)&Sbuf[Sidx];
 1763:   while( isspace(*ch) ) { ch++; inc++; sp=1; }
 1764:   Sidx = Sidx + inc;
 1765:   if( (*ch == '*')  || (*ch == '/') || (*ch == '+')  || (*ch == '-') || (*ch == '^') ) {
 1766:     Sidx++;
 1767:     /* print_remains();  printf(" op))"); printf("\n"); */
 1768:     return (*ch);
 1769:   }
 1770:   /* print_remains();  printf(" op))"); printf("\n"); */
 1771:   /* what if space is the last thing on the line?*/
 1772:   if( sp  && (*ch != '\0')) return '*';
 1773:   return (*ch);
 1774: }
 1775: 
 1776: int
 1777: s_getnext()
 1778: {
 1779:   char  ch;
 1780:   
 1781:   ch = Sbuf[Sidx];
 1782:   Sidx++;
 1783:   return (ch);
 1784: }
 1785: 
 1786: int
 1787: s_peeknext()
 1788: {
 1789:   char  ch;
 1790:   
 1791:   ch = Sbuf[Sidx];
 1792:   return (ch);
 1793: }
 1794: 
 1795: int
 1796: s_peeknextNW()  /* peek into the next non-whitespaces character */
 1797: {
 1798:   char  *ch;
 1799: 
 1800:   ch = (char *)&Sbuf[Sidx];
 1801:   while( isspace(*ch) ) { ch++; }
 1802:   return (*ch);
 1803: }
 1804: 
 1805: int
 1806: s_getnextNW()  /* get the next non-whitespaces character */
 1807: {
 1808:   char  *ch;
 1809: 
 1810:   ch = (char *)&Sbuf[Sidx]; Sidx++;
 1811:   while( isspace(*ch) ) { ch++; Sidx++; }
 1812:   return (*ch);
 1813: }
 1814: /* peek into the next non-whitespaces character 
 1815:    which should be either a multiply or division */
 1816: int
 1817: s_peekMDWS()  
 1818: {
 1819:   char  *ch;
 1820:   int    sp=0;
 1821:   
 1822:   ch = (char *)&Sbuf[Sidx];
 1823:   while( isspace(*ch) ) { ch++; sp=1;}
 1824:   if( (*ch == '*')  || (*ch == '/') ) {
 1825:     return (*ch);
 1826:   }
 1827:   if( sp ) return ' ';
 1828:   ch = (char *)&Sbuf[Sidx];
 1829:   while( isspace(*ch) ) { ch++; }
 1830:   return (*ch);
 1831: }
 1832: 
 1833: int
 1834: s_getnextMDWS()
 1835: {
 1836:   char  *ch;
 1837:   int    inc=0, sp=0;
 1838:   
 1839:   ch = (char *)&Sbuf[Sidx]; Sidx++;
 1840:   while( isspace(*ch) ) { ch++; inc++; sp=1; }
 1841:   Sidx += inc;
 1842:   if( (*ch == '*')  || (*ch == '/') ) {
 1843:     return (*ch);
 1844:   }
 1845:   if( sp ) return ' ';
 1846:   return (*ch);
 1847: }
 1848: 
 1849: double
 1850: scan_FLOAT()
 1851: {
 1852:   double   num; 
 1853:   int      ii=0, len;
 1854:   char     num_str[QUARTER_K];
 1855:   
 1856:   num_str[ii]=0;
 1857:   while( isspace(Sbuf[Sidx]) ) { Sidx++; }
 1858:   if( Sbuf[Sidx] == '-' ) {
 1859:     num_str[ii++] = Sbuf[Sidx++];
 1860:   }
 1861:   while( isdigit(Sbuf[Sidx]) || Sbuf[Sidx] == '.' ) {
 1862:       num_str[ii++] = Sbuf[Sidx++];
 1863:   }
 1864:   if( Sbuf[Sidx] == 'E' || Sbuf[Sidx] == 'e' ) {
 1865:     if( Sbuf[Sidx+1] == '-' || isdigit(Sbuf[Sidx+1]) ) {
 1866:       num_str[ii++] = Sbuf[Sidx++];
 1867:       num_str[ii++] = Sbuf[Sidx++];
 1868:       while( isdigit(Sbuf[Sidx]) ) {
 1869:         num_str[ii++] = Sbuf[Sidx++];
 1870:       }
 1871:     }
 1872:   }
 1873:   num_str[ii] = 0; /* terminate the str */
 1874:   len = strlen(num_str);
 1875:   if(len > 0 ) {
 1876:     sscanf(num_str,"%lg", &num);
 1877:     /* printf("<N %s %g>",num_str,num); fflush(stdout);  print_remains(); */
 1878:   } else {
 1879:     num = 1.0;
 1880:   }
 1881:   return (num);
 1882: }
 1883: /* -----------------------------------------------
 1884:   N.item  := FLOAT
 1885:            | FLOAT '^' N.term
 1886:    ----------------------------------------------- */
 1887: Unit_t  *
 1888: scan_num_item()
 1889: {
 1890:   Unit_t  *node_p, *exp_p;
 1891:   double   num_const;
 1892:   char     ch;
 1893:   
 1894:   num_const = scan_FLOAT();
 1895:   node_p = p_new_num(NULL, num_const, NULL);
 1896:   ch = s_peeknext_op();
 1897:   if( ch == '^' ) {
 1898:     ch = s_getnext_op();
 1899:     
 1900:     exp_p = scan_num_term();
 1901:     num_const = node_p->u_scale;
 1902:     if( node_p->u_scale > 0.0 ) {
 1903:       num_const = pow(node_p->u_scale,exp_p->u_scale);
 1904:     }
 1905:     node_p->u_scale = num_const;
 1906:     capa_mfree((char *)exp_p);
 1907:   }
 1908:   return node_p;
 1909: }
 1910: 
 1911: /* -----------------------------------------------
 1912:   U.item  := UNIT
 1913:            | UNIT '^' N.term
 1914:    ----------------------------------------------- */
 1915:    
 1916: Unit_t *
 1917: scan_unit_item()
 1918: {
 1919:   Unit_t   *node_p, *exp_p;
 1920:   char      ch;
 1921:   double   num_const;
 1922:   Unit_E   *oe_p;
 1923:   
 1924:   node_p = p_new_unit(NULL,NULL);
 1925:   ch = s_peeknext_op();
 1926:   if( ch == '^' ) {
 1927:     ch = s_getnext_op();
 1928:     exp_p = scan_num_term();
 1929:     num_const = exp_p->u_scale;
 1930:     if( node_p->u_count > 0 ) {
 1931:       oe_p = node_p->u_list;
 1932:       for(oe_p = node_p->u_list; oe_p; oe_p = oe_p->ue_nextp ) {
 1933:         oe_p->ue_exp   = oe_p->ue_exp * num_const;
 1934:       }
 1935:     }
 1936:     num_const = node_p->u_scale;
 1937:     if( node_p->u_scale > 0.0 ) {
 1938:       num_const = pow(node_p->u_scale,exp_p->u_scale);
 1939:     }
 1940:     node_p->u_scale = num_const;
 1941:     capa_mfree((char *)exp_p);
 1942:   }
 1943:   return node_p;
 1944: }
 1945: 
 1946: void distribute_exp(Unit_t* node_p,Unit_t* exp_p) 
 1947: {
 1948:   Unit_E* oe_p;
 1949:   double num_const;
 1950:   num_const = exp_p->u_scale;  /* should we check if num_const too large or small ? */
 1951:   if( node_p->u_count > 0 ) {
 1952:     oe_p = node_p->u_list;
 1953:     for(oe_p = node_p->u_list; oe_p; oe_p = oe_p->ue_nextp ) {
 1954:       oe_p->ue_exp   = oe_p->ue_exp * num_const;
 1955:     }
 1956:   }
 1957:   num_const = node_p->u_scale;
 1958:   if( node_p->u_scale > 0.0 ) {  /* what if u_scale <= 0.0 ? */
 1959:     num_const = pow(node_p->u_scale,exp_p->u_scale);
 1960:   }
 1961:   node_p->u_scale = num_const;
 1962:   if (node_p->u_left) distribute_exp(node_p->u_left,exp_p);
 1963:   if (node_p->u_right) distribute_exp(node_p->u_right,exp_p);
 1964: }
 1965: 
 1966: /* ---------------------------------------------------------------
 1967:    B.term  := U.item
 1968:            | N.item
 1969:            | '(' B.block ')'
 1970:            | '{' B.block '}'
 1971:            
 1972:            | '(' B.block ')' '^' N.term  <== July 6 1998
 1973:            | '{' B.block '}' '^' N.term
 1974:            
 1975:    --------------------------------------------------------------- */
 1976: Unit_t *
 1977: scan_basic_term()
 1978: {
 1979:   Unit_t   *node_p, *exp_p;
 1980:   int       ch, nch;
 1981:   
 1982:   ch = s_peeknextNW();
 1983:   if( ch == '(' || ch == '{' ) {
 1984:     ch = s_getnextNW();  /* get rid of '(' or '{' */
 1985:     node_p = scan_basic_block();
 1986:     nch = s_peeknextNW();
 1987:     if( nch == ')' || nch == '}' ) {  /* should be either ')' or '}' */
 1988:       if( ((ch == '(' ) && (nch == ')' )) ||
 1989:           ((ch == '{' ) && (nch == '}' )) ) { /* matching left paren with right paren */
 1990:           
 1991:            
 1992:       } else {
 1993:         /* printf(" WARN: %c matched by %c\n", ch, nch); */
 1994:       }
 1995:       nch = s_getnextNW();
 1996:       /* ====== Added Jul 6, 1998 ====> */
 1997:       ch = s_peeknext_op();
 1998:       if( ch == '^' ) {
 1999:         ch = s_getnext_op();  /* get rid of '^' char */
 2000:         exp_p = scan_num_term();
 2001: 	distribute_exp(node_p,exp_p);
 2002:         capa_mfree((char *)exp_p);
 2003:       } 
 2004:       /* <== added Jul 6, 1998 == */
 2005:     } else {
 2006:       /* printf(" WARN: %c is not matched by %c\n", ch, nch); */
 2007:     }
 2008:   } else if( ch >= '0' && ch <= '9' ) {
 2009:     node_p = scan_num_item();
 2010:   } else { /* assume a unit symbol */
 2011:     /* printf("<B.term>"); print_remains(); */
 2012:     node_p = scan_unit_item();
 2013:     /* print_remains(); */
 2014:   }
 2015:   return node_p;
 2016: }
 2017: /* --------------------------------------------------
 2018:    N.term  := N.item
 2019:            | '-' N.item
 2020:            | '(' N.expr ')'
 2021:            | '{' N.expr '}'
 2022:  -------------------------------------------------- */
 2023: Unit_t *
 2024: scan_num_term()
 2025: {
 2026:   Unit_t   *node_p;
 2027:   char      ch, nch;
 2028: 
 2029:   ch = s_peeknextNW();
 2030:   if( ch == '(' || ch == '{' ) {
 2031:     ch = s_getnextNW();
 2032:     node_p = scan_num_expr();
 2033:     nch = s_peeknextNW();
 2034:     if( nch == ')' || nch == '}' ) {  /* should be either ')' or '}' */
 2035:       if( ((ch == '(' ) && (nch == ')' )) ||
 2036:           ((ch == '{' ) && (nch == '}' )) ) { 
 2037:         
 2038:       } else {
 2039:         /* printf(" WARN: %c matched by %c\n", ch, nch); */
 2040:       }
 2041:       nch = s_getnextNW();
 2042:     } else {
 2043:       /* printf(" WARN: %c is not matched by %c\n", ch, ch); */
 2044:     }
 2045:   } else if( ch == '-' ) {
 2046:     ch = s_getnextNW();
 2047:     node_p = scan_num_item();
 2048:     node_p->u_scale = (-1)*node_p->u_scale;
 2049:   } else {
 2050:     if( isdigit(ch) ) {
 2051:        node_p = scan_num_item();
 2052:     } else { /* something other than a number */
 2053:        /*
 2054:           printf(" ERROR: expect a number: ");
 2055:           print_remains();
 2056:        */
 2057:        node_p = p_new_num(NULL, 0.0, NULL); /* make the unknown item */
 2058:     }
 2059:   }
 2060:   return node_p;
 2061: }
 2062: 
 2063: /* --------------------------------------------------
 2064:    B.block := B.term
 2065:            | B.term ' ' B.term
 2066:            | B.term '*' B.term
 2067:            | B.term '/' B.term
 2068:    -------------------------------------------------- */
 2069: Unit_t  *
 2070: scan_basic_block()
 2071: {
 2072:   Unit_t   *node_p;
 2073:   char      ch;
 2074:   int       op;
 2075:   
 2076:   /* printf("<B.block>(before B.term)"); print_remains(); */
 2077:   node_p = scan_basic_term();
 2078:   ch = s_peeknext_op();
 2079:   while ( ch == '*' || ch == '/' ) {
 2080:     op = ( ch == '/' ? U_OP_DIVIDE : U_OP_TIMES);
 2081:     ch = s_getnext_op();
 2082:     /* printf("<B.block>(/ *)"); print_remains();  */
 2083:     node_p = p_new_op(node_p,op,scan_basic_term());
 2084:     ch = s_peeknext_op();
 2085:   }
 2086:   return node_p;
 2087: }
 2088: /* --------------------------------------------------
 2089:    N.block := N.term 
 2090:            | N.term ' ' N.term
 2091:            | N.term '*' N.term
 2092:            | N.term '/' N.term
 2093:    -------------------------------------------------- */
 2094: Unit_t  *
 2095: scan_num_block()
 2096: {
 2097:   Unit_t   *node_p, *opand_p;
 2098:   char      ch;
 2099:   double    result;
 2100:   
 2101:   node_p = scan_num_term();
 2102:   ch = s_peeknext_op();
 2103:   while ( ch == '*' || ch == '/' ) {
 2104:     s_getnext_op();
 2105:     opand_p = scan_num_term();
 2106:     if( ch == '*' ) {
 2107:       result = node_p->u_scale * opand_p->u_scale;
 2108:     } else {
 2109:       result = node_p->u_scale / opand_p->u_scale;
 2110:     }
 2111:     node_p->u_scale = result;
 2112:     capa_mfree((char *)opand_p);
 2113:     ch = s_peeknext_op();
 2114:   }
 2115:   return node_p;
 2116: }
 2117: 
 2118: /* ---------------------------------------
 2119:    U.expr  := B.block
 2120:            | B.block '+' B.block
 2121:            | B.block '-' B.block
 2122:    --------------------------------------- */
 2123: Unit_t  *
 2124: scan_unit_expr()
 2125: {
 2126:   Unit_t   *node_p;
 2127:   char      ch;
 2128:   int       op;
 2129:   
 2130:   /* printf("<U.expr>"); print_remains();  */
 2131:   node_p = scan_basic_block();
 2132:   ch = s_peeknext_op();
 2133:   while ( ch == '+' || ch == '-' ) {
 2134:     op = ( ch == '+' ? U_OP_PLUS : U_OP_MINUS);
 2135:     ch = s_getnext_op();
 2136:     /* printf("<U.expr>(+-)"); print_remains(); */
 2137:     node_p = p_new_op(node_p,op,scan_basic_block());
 2138:     ch = s_peeknext_op();
 2139:   }
 2140:   return node_p;
 2141: }
 2142: /* -----------------------------------------
 2143:    N.expr  := N.block 
 2144:            | N.block '+' N.block
 2145:            | N.block '-' N.block
 2146:    ----------------------------------------- */
 2147: Unit_t  *
 2148: scan_num_expr()
 2149: {
 2150:   Unit_t   *node_p, *opand_p;
 2151:   char      ch;
 2152:   double    result;
 2153:   
 2154:   node_p = scan_num_block();
 2155:   ch = s_peeknext_op();
 2156:   while ( ch == '+' || ch == '-' ) {
 2157:     ch = s_getnext_op();
 2158:     opand_p = scan_num_block();
 2159:     if( ch == '+' ) {
 2160:       result = node_p->u_scale + opand_p->u_scale;
 2161:     } else {
 2162:       result = node_p->u_scale - opand_p->u_scale;
 2163:     }
 2164:     node_p->u_scale = result;
 2165:     capa_mfree((char *)opand_p);
 2166:     ch = s_peeknext_op();
 2167:   }
 2168:   return node_p;
 2169: }
 2170: 
 2171: /* ----------------------------------------------------------------------- */
 2172: /* <--  This is the major entry point to parse an units expression ------> */
 2173: Unit_t  *
 2174: parse_unit_expr(char *symb_str)
 2175: {
 2176:   Unit_t   *root_p;
 2177:   int       len;
 2178:   
 2179:   len = strlen(symb_str);
 2180:   strcpy(Sbuf,symb_str);  /* copy it into the global Sbuf */
 2181:   Sidx=0;
 2182:   root_p = scan_unit_expr();
 2183:   if(Sidx < len-1 ) {
 2184:     /* printf(" WARN: NOT PARSED:");  print_remains(); */
 2185:   }
 2186:   return (root_p);
 2187: 
 2188: }
 2189: 
 2190: void
 2191: print_remains()
 2192: {
 2193:   int       len, ii;
 2194:   
 2195:   len = strlen(Sbuf);
 2196:   printf("[[");
 2197:   for(ii=Sidx;ii<len;ii++) {
 2198:       printf("%c",Sbuf[ii]);
 2199:   }
 2200:   printf("]]");
 2201:   
 2202: }
 2203: 
 2204: 
 2205: 
 2206: /* =================================================================== */

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