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