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