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