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