Annotation of capa/capa51/pProj/capaUnit.c, revision 1.4
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:
1.4 ! albertel 635: /* returns 1 on okay, 2 on error*/
1.1 albertel 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));
1.4 ! albertel 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: }
1.1 albertel 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
1.4 ! albertel 738: if ((ufp=fopen("unit.DBUG","a"))==NULL) { fprintf(stderr,"Error: can't open login debug\n"); return UNIT_FAIL; }
1.1 albertel 739: #endif
740:
1.3 albertel 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:
1.1 albertel 746: ap = parse_unit_expr(u_symb);
747: Ptopidx=0;
1.4 ! albertel 748:
! 749: if (postwalk_utree(ap)==1) {
1.1 albertel 750: #ifdef UNIT_DBUG
1.4 ! albertel 751: fprintf(ufp,"Ptopidx %d\n",Ptopidx);
1.1 albertel 752: #endif
1.4 ! albertel 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;
1.1 albertel 765: }
1.4 ! albertel 766: } else { /* invalid unit representation */
1.1 albertel 767: result = UNIT_FAIL;
768: }
1.4 ! albertel 769: } else {
1.1 albertel 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 {
1.2 albertel 875: if( b_p->u_type == U_BASE ) {
1.1 albertel 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++;
1.2 albertel 889: } else if( b_p->u_type == U_DERIVED) {
890: /* derived units but without any units elements (scalar) */
1.4 ! albertel 891: /* do nothing, ignore this units WE REALLY MEAN THIS DON'T DO THE NEXT LINE!*/
! 892: /*a_p->u_count++;*/
1.1 albertel 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);
1.2 albertel 1386: /*
1387: printf("Derived Unit:%s\n",new_p->u_name);
1388: print_unit_t(new_p);
1389: */
1.1 albertel 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: }
1.2 albertel 1435: /*
1436: printf("Before Simplify:: \n");
1437: print_unit_t(u_p);
1438: */
1.1 albertel 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: }
1.2 albertel 1450: /* debugging
1.1 albertel 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: }
1.2 albertel 1455: if( CExp[ii] == 0.0 ) {
1456: printf("(%d)%s,S=%g,Exp=%g\n",ii,CSymb[ii],CScale[ii], CExp[ii]);
1457: }
1.1 albertel 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: }
1.2 albertel 1480: /*
1481: printf("After Simplify:: \n");
1482: print_unit_t(u_p);
1483: */
1.1 albertel 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;
1.4 ! albertel 1720: cu_p->u_type = U_UNKNOWN;
1.1 albertel 1721: }
1722: } else {
1723: /* printf("<<%s>>", symb_str); */
1724: err_code = 2;
1.4 ! albertel 1725: cu_p->u_type = U_UNKNOWN;
1.1 albertel 1726: }
1727: } else {/* len == 1 */
1728: /* printf(" not found\n"); */
1729: err_code = 1;
1.4 ! albertel 1730: cu_p->u_type = U_UNKNOWN;
1.1 albertel 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>