1    	/*
2    	 * Copyright (c) 1995 Silicon Graphics, Inc.  All Rights Reserved.
3    	 * 
4    	 * This library is free software; you can redistribute it and/or modify it
5    	 * under the terms of the GNU Lesser General Public License as published
6    	 * by the Free Software Foundation; either version 2.1 of the License, or
7    	 * (at your option) any later version.
8    	 * 
9    	 * This library is distributed in the hope that it will be useful, but
10   	 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11   	 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
12   	 * License for more details.
13   	 */
14   	
15   	#include "pmapi.h"
16   	#include "impl.h"
17   	#include <math.h>
18   	#include <inttypes.h>
19   	
20   	#ifndef ABS
21   	#define    ABS(a)          ((a) < 0 ? -(a) : (a))
22   	#endif
23   	
24   	#if defined(HAVE_CONST_LONGLONG)
25   	#define SIGN_64_MASK 0x8000000000000000LL
26   	#else
27   	#define SIGN_64_MASK 0x8000000000000000
28   	#endif
29   	
30   	/* pmAtomValue -> string, max length is 40 bytes */
31   	const char *
32   	pmAtomStr(const pmAtomValue *avp, int type)
33   	{
34   	    int		i;
35   	    static char	buf[80];
36   	    pmAtomValue	av;
37   	    int		vlen;
38   	
39   	    /* avoid alignment problems ... avp may be unaligned! */
40   	    memcpy((void *)&av, (void *)avp, sizeof(av));
41   	
42   	    switch (type) {
43   		case PM_TYPE_32:
44   		    snprintf(buf, sizeof(buf), "%d", av.l);
45   		    break;
46   		case PM_TYPE_U32:
47   		    snprintf(buf, sizeof(buf), "%u", av.ul);
48   		    break;
49   		case PM_TYPE_64:
50   		    snprintf(buf, sizeof(buf), "%"PRIi64, av.ll);
51   		    break;
52   		case PM_TYPE_U64:
53   		    snprintf(buf, sizeof(buf), "%"PRIu64, av.ull);
54   		    break;
55   		case PM_TYPE_FLOAT:
56   		    snprintf(buf, sizeof(buf), "%e", (double)av.f);
57   		    break;
58   		case PM_TYPE_DOUBLE:
59   		    snprintf(buf, sizeof(buf), "%e", av.d);
60   		    break;
61   		case PM_TYPE_STRING:
62   		    if (av.cp == NULL)
63   			snprintf(buf, sizeof(buf), "<null>");
64   		    else {
65   			i = (int)strlen(av.cp);
66   			if (i < 38)
67   			    snprintf(buf, sizeof(buf), "\"%s\"", av.cp);
68   			else
69   			    snprintf(buf, sizeof(buf), "\"%34.34s...\"", av.cp);
70   		    }
71   		    break;
72   		case PM_TYPE_AGGREGATE:
73   		case PM_TYPE_AGGREGATE_STATIC:
74   		    if (av.vbp == NULL) {
75   			snprintf(buf, sizeof(buf), "<null>");
76   			break;
77   		    }
78   		    vlen = av.vbp->vlen - PM_VAL_HDR_SIZE;
79   		    if (vlen == 0)
80   			snprintf(buf, sizeof(buf), "[type=%s len=%d]", pmTypeStr(av.vbp->vtype), vlen);
81   		    else {
82   			char	*cp;
83   			char	*bp;
84   			snprintf(buf, sizeof(buf), "[type=%s len=%d]", pmTypeStr(av.vbp->vtype), vlen);
85   			cp = (char *)av.vbp->vbuf;
86   			for (i = 0; i < vlen && i < 12; i++) {
87   			    bp = &buf[strlen(buf)];
88   			    if ((i % 4) == 0)
89   				snprintf(bp, sizeof(buf) - (bp-buf), " %02x", *cp & 0xff);
90   			    else
91   				snprintf(bp, sizeof(buf) - (bp-buf), "%02x", *cp & 0xff);
92   			    cp++;
93   			}
94   			if (vlen > 12) {
95   			    bp = &buf[strlen(buf)];
96   			    snprintf(bp, sizeof(buf) - (bp-buf), " ...");
97   			}
98   		    }
99   		    break;
100  		case PM_TYPE_EVENT:
101  		    {
102  			/* have to assume alignment is OK in this case */
103  			pmEventArray	*eap = (pmEventArray *)avp->vbp;
104  			if (eap->ea_nrecords == 1)
105  			    snprintf(buf, sizeof(buf), "[1 event record]");
106  			else
107  			    snprintf(buf, sizeof(buf), "[%d event records]", eap->ea_nrecords);
108  		    }
109  		    break;
110  		default:
111  		    snprintf(buf, sizeof(buf), "Error: unexpected type: %s", pmTypeStr(type));
112  	    }
113  	    return buf;
114  	}
115  	
116  	/*
117  	 * must be in agreement with ordinal values for PM_TYPE_* #defines
118  	 */
119  	static char *typename[] = {
120  	    "32", "U32", "64", "U64", "FLOAT", "DOUBLE", "STRING", "AGGREGATE", "AGGREGATE_STATIC", "EVENT"
121  	};
122  	
123  	/* PM_TYPE_* -> string, max length is 20 bytes */
124  	const char *
125  	pmTypeStr(int type)
126  	{
127  	    static char	buf[30];
128  	    if (type >= 0 && type < sizeof(typename)/sizeof(typename[0]))
129  		snprintf(buf, sizeof(buf), "%s", typename[type]);
130  	    else if (type == PM_TYPE_NOSUPPORT)
131  		strcpy(buf, "Not Supported");
132  	    else if (type == PM_TYPE_UNKNOWN)
133  		strcpy(buf, "Unknown");
134  	    else
135  		snprintf(buf, sizeof(buf), "Illegal type=%d", type);
136  	
137  	    return buf;
138  	}
139  	
140  	/* scale+units -> string, max length is 60 bytes */
141  	const char *
142  	pmUnitsStr(const pmUnits *pu)
143  	{
144  	    char	*spacestr = NULL;
145  	    char	*timestr = NULL;
146  	    char	*countstr = NULL;
147  	    char	*p;
148  	    char	sbuf[20];
149  	    char	tbuf[20];
150  	    char	cbuf[20];
151  	    static char	buf[60];
152  	
153  	    buf[0] = '\0';
154  	
155  	    if (pu->dimSpace) {
156  		switch (pu->scaleSpace) {
157  		    case PM_SPACE_BYTE:
158  			spacestr = "byte";
159  			break;
160  		    case PM_SPACE_KBYTE:
161  			spacestr = "Kbyte";
162  			break;
163  		    case PM_SPACE_MBYTE:
164  			spacestr = "Mbyte";
165  			break;
166  		    case PM_SPACE_GBYTE:
167  			spacestr = "Gbyte";
168  			break;
169  		    case PM_SPACE_TBYTE:
170  			spacestr = "Tbyte";
171  			break;
172  		    case PM_SPACE_PBYTE:
173  			spacestr = "Pbyte";
174  			break;
175  		    case PM_SPACE_EBYTE:
176  			spacestr = "Ebyte";
177  			break;
178  		    default:
179  			snprintf(sbuf, sizeof(sbuf), "space-%d", pu->scaleSpace);
180  			spacestr = sbuf;
181  			break;
182  		}
183  	    }
184  	    if (pu->dimTime) {
185  		switch (pu->scaleTime) {
186  		    case PM_TIME_NSEC:
187  			timestr = "nanosec";
188  			break;
189  		    case PM_TIME_USEC:
190  			timestr = "microsec";
191  			break;
192  		    case PM_TIME_MSEC:
193  			timestr = "millisec";
194  			break;
195  		    case PM_TIME_SEC:
196  			timestr = "sec";
197  			break;
198  		    case PM_TIME_MIN:
199  			timestr = "min";
200  			break;
201  		    case PM_TIME_HOUR:
202  			timestr = "hour";
203  			break;
204  		    default:
205  			snprintf(tbuf, sizeof(tbuf), "time-%d", pu->scaleTime);
206  			timestr = tbuf;
207  			break;
208  		}
209  	    }
210  	    if (pu->dimCount) {
211  		switch (pu->scaleCount) {
212  		    case 0:
213  			countstr = "count";
214  			break;
215  		    case 1:
216  			snprintf(cbuf, sizeof(cbuf), "count x 10");
217  			countstr = cbuf;
218  			break;
219  		    default:
220  			snprintf(cbuf, sizeof(cbuf), "count x 10^%d", pu->scaleCount);
221  			countstr = cbuf;
222  			break;
223  		}
224  	    }
225  	
226  	    p = buf;
227  	
228  	    if (pu->dimSpace > 0) {
229  		if (pu->dimSpace == 1)
230  		    snprintf(p, sizeof(buf), "%s", spacestr);
231  		else
232  		    snprintf(p, sizeof(buf), "%s^%d", spacestr, pu->dimSpace);
233  		while (*p) p++;
234  		*p++ = ' ';
235  	    }
236  	    if (pu->dimTime > 0) {
237  		if (pu->dimTime == 1)
238  		    snprintf(p, sizeof(buf) - (p - buf), "%s", timestr);
239  		else
240  		    snprintf(p, sizeof(buf) - (p - buf), "%s^%d", timestr, pu->dimTime);
241  		while (*p) p++;
242  		*p++ = ' ';
243  	    }
244  	    if (pu->dimCount > 0) {
245  		if (pu->dimCount == 1)
246  		    snprintf(p, sizeof(buf) - (p - buf), "%s", countstr);
247  		else
248  		    snprintf(p, sizeof(buf) - (p - buf), "%s^%d", countstr, pu->dimCount);
249  		while (*p) p++;
250  		*p++ = ' ';
251  	    }
252  	    if (pu->dimSpace < 0 || pu->dimTime < 0 || pu->dimCount < 0) {
253  		*p++ = '/';
254  		*p++ = ' ';
255  		if (pu->dimSpace < 0) {
256  		    if (pu->dimSpace == -1)
257  			snprintf(p, sizeof(buf) - (p - buf), "%s", spacestr);
258  		    else
259  			snprintf(p, sizeof(buf) - (p - buf), "%s^%d", spacestr, -pu->dimSpace);
260  		    while (*p) p++;
261  		    *p++ = ' ';
262  		}
263  		if (pu->dimTime < 0) {
264  		    if (pu->dimTime == -1)
265  			snprintf(p, sizeof(buf) - (p - buf), "%s", timestr);
266  		    else
267  			snprintf(p, sizeof(buf) - (p - buf), "%s^%d", timestr, -pu->dimTime);
268  		    while (*p) p++;
269  		    *p++ = ' ';
270  		}
271  		if (pu->dimCount < 0) {
272  		    if (pu->dimCount == -1)
273  			snprintf(p, sizeof(buf) - (p - buf), "%s", countstr);
274  		    else
275  			snprintf(p, sizeof(buf) - (p - buf), "%s^%d", countstr, -pu->dimCount);
276  		    while (*p) p++;
277  		    *p++ = ' ';
278  		}
279  	    }
280  	
281  	    if (buf[0] == '\0') {
282  		/*
283  		 * dimension is all 0, but scale maybe specified ... small
284  		 * anomaly here as we would expect dimCount to be 1 not
285  		 * 0 for these cases, but support maintained for historical
286  		 * behaviour
287  		 */
288  		if (pu->scaleCount == 1)
289  		    snprintf(buf, sizeof(buf), "x 10");
290  		else if (pu->scaleCount != 0)
291  		    snprintf(buf, sizeof(buf), "x 10^%d", pu->scaleCount);
292  	    }
293  	    else {
294  		p--;
295  		*p = '\0';
296  	    }
297  	
298  	    return buf;
299  	}
300  	
301  	/* Scale conversion, based on value format, value type and scale */
302  	int
303  	pmConvScale(int type, const pmAtomValue *ival, const pmUnits *iunit,
304  		    pmAtomValue *oval, const pmUnits *ounit)
305  	{
306  	    int			sts;
307  	    int			k;
308  	    __int64_t		div, mult;
309  	    __int64_t		d, m;
310  	
311  	#ifdef PCP_DEBUG
312  	    if (pmDebug & DBG_TRACE_VALUE) {
313  		fprintf(stderr, "pmConvScale: %s", pmAtomStr(ival, type));
314  		fprintf(stderr, " [%s]", pmUnitsStr(iunit));
315  	    }
316  	#endif
317  	
318  	    if (iunit->dimSpace != ounit->dimSpace ||
319  		iunit->dimTime != ounit->dimTime ||
320  		iunit->dimCount != ounit->dimCount) {
321  		    sts = PM_ERR_CONV;
322  		    goto bad;
323  	    }
324  	
325  	    div = mult = 1;
326  	
327  	    if (iunit->dimSpace) {
328  		d = 1;
329  		m = 1;
330  		switch (iunit->scaleSpace) {
331  		    case PM_SPACE_BYTE:
332  			d = 1024 * 1024;
333  			break;
334  		    case PM_SPACE_KBYTE:
335  			d = 1024;
336  			break;
337  		    case PM_SPACE_MBYTE:
338  			/* the canonical unit */
339  			break;
340  		    case PM_SPACE_GBYTE:
341  			m = 1024;
342  			break;
343  		    case PM_SPACE_TBYTE:
344  			m = 1024 * 1024;
345  			break;
346  		    case PM_SPACE_PBYTE:
347  			m = 1024 * 1024 * 1024;
348  			break;
349  		    case PM_SPACE_EBYTE:
350  			m = (__int64_t)1024 * 1024 * 1024 * 1024;
351  			break;
352  		    default:
353  			sts = PM_ERR_UNIT;
354  			goto bad;
355  		}
356  		switch (ounit->scaleSpace) {
357  		    case PM_SPACE_BYTE:
358  			m *= 1024 * 1024;
359  			break;
360  		    case PM_SPACE_KBYTE:
361  			m *= 1024;
362  			break;
363  		    case PM_SPACE_MBYTE:
364  			/* the canonical unit */
365  			break;
366  		    case PM_SPACE_GBYTE:
367  			d *= 1024;
368  			break;
369  		    case PM_SPACE_TBYTE:
370  			d *= 1024 * 1024;
371  			break;
372  		    case PM_SPACE_PBYTE:
373  			d *= 1024 * 1024 * 1024;
374  			break;
375  		    case PM_SPACE_EBYTE:
376  			d *= (__int64_t)1024 * 1024 * 1024 * 1024;
377  			break;
378  		    default:
379  			sts = PM_ERR_UNIT;
380  			goto bad;
381  		}
382  		if (iunit->dimSpace > 0) {
383  		    for (k = 0; k < iunit->dimSpace; k++) {
384  			div *= d;
385  			mult *= m;
386  		    }
387  		}
388  		else {
389  		    for (k = iunit->dimSpace; k < 0; k++) {
390  			mult *= d;
391  			div *= m;
392  		    }
393  		}
394  	    }
395  	
396  	    if (iunit->dimTime) {
397  		d = 1;
398  		m = 1;
399  		switch (iunit->scaleTime) {
400  		    case PM_TIME_NSEC:
401  			d = 1000000000;
402  			break;
403  		    case PM_TIME_USEC:
404  			d = 1000000;
405  			break;
406  		    case PM_TIME_MSEC:
407  			d = 1000;
408  			break;
409  		    case PM_TIME_SEC:
410  			/* the canonical unit */
411  			break;
412  		    case PM_TIME_MIN:
413  			m = 60;
414  			break;
415  		    case PM_TIME_HOUR:
416  			m = 3600;
417  			break;
418  		    default:
419  			sts = PM_ERR_UNIT;
420  			goto bad;
421  		}
422  		switch (ounit->scaleTime) {
423  		    case PM_TIME_NSEC:
424  			m *= 1000000000;
425  			break;
426  		    case PM_TIME_USEC:
427  			m *= 1000000;
428  			break;
429  		    case PM_TIME_MSEC:
430  			m *= 1000;
431  			break;
432  		    case PM_TIME_SEC:
433  			/* the canonical unit */
434  			break;
435  		    case PM_TIME_MIN:
436  			d *= 60;
437  			break;
438  		    case PM_TIME_HOUR:
439  			d *= 3600;
440  			break;
441  		    default:
442  			sts = PM_ERR_UNIT;
443  			goto bad;
444  		}
445  		if (iunit->dimTime > 0) {
446  		    for (k = 0; k < iunit->dimTime; k++) {
447  			div *= d;
448  			mult *= m;
449  		    }
450  		}
451  		else {
452  		    for (k = iunit->dimTime; k < 0; k++) {
453  			mult *= d;
454  			div *= m;
455  		    }
456  		}
457  	    }
458  	
459  	    if (iunit->dimCount ||
460  		(iunit->dimSpace == 0 && iunit->dimTime == 0)) {
461  		d = 1;
462  		m = 1;
463  		if (iunit->scaleCount < 0) {
464  		    for (k = iunit->scaleCount; k < 0; k++)
465  			d *= 10;
466  		}
467  		else if (iunit->scaleCount > 0) {
468  		    for (k = 0; k < iunit->scaleCount; k++)
469  			m *= 10;
470  		}
471  		if (ounit->scaleCount < 0) {
472  		    for (k = ounit->scaleCount; k < 0; k++)
473  			m *= 10;
474  		}
475  		else if (ounit->scaleCount > 0) {
476  		    for (k = 0; k < ounit->scaleCount; k++)
477  			d *= 10;
478  		}
479  		if (iunit->dimCount > 0) {
480  		    for (k = 0; k < iunit->dimCount; k++) {
481  			div *= d;
482  			mult *= m;
483  		    }
484  		}
485  		else if (iunit->dimCount < 0) {
486  		    for (k = iunit->dimCount; k < 0; k++) {
487  			mult *= d;
488  			div *= m;
489  		    }
490  		}
491  		else {
492  		    mult = m;
493  		    div = d;
494  		}
495  	    }
496  	
497  	    if (mult % div == 0) {
498  		mult /= div;
499  		div = 1;
500  	    }
501  	
502  	    switch (type) {
503  		case PM_TYPE_32:
504  			oval->l = (__int32_t)((ival->l * mult + div/2) / div);
505  			break;
506  		case PM_TYPE_U32:
507  			oval->ul = (__uint32_t)((ival->ul * mult + div/2) / div);
508  			break;
509  		case PM_TYPE_64:
510  			oval->ll = (ival->ll * mult + div/2) / div;
511  			break;
512  		case PM_TYPE_U64:
513  			oval->ull = (ival->ull * mult + div/2) / div;
514  			break;
515  		case PM_TYPE_FLOAT:
516  			oval->f = ival->f * ((float)mult / (float)div);
517  			break;
518  		case PM_TYPE_DOUBLE:
519  			oval->d = ival->d * ((double)mult / (double)div);
520  			break;
521  		default:
522  			sts = PM_ERR_CONV;
523  			goto bad;
524  	    }
525  	
526  	#ifdef PCP_DEBUG
527  	    if (pmDebug & DBG_TRACE_VALUE) {
528  		fprintf(stderr, " -> %s", pmAtomStr(oval, type));
529  		fprintf(stderr, " [%s]\n", pmUnitsStr(ounit));
530  	    }
531  	#endif
532  	    return 0;
533  	
534  	bad:
535  	#ifdef PCP_DEBUG
536  	    if (pmDebug & DBG_TRACE_VALUE) {
537  		fprintf(stderr, " -> Error: %s", pmErrStr(sts));
538  		fprintf(stderr, " [%s]\n", pmUnitsStr(ounit));
539  	    }
540  	#endif
541  	    return sts;
542  	}
543  	
544  	/* Value extract from pmValue and type conversion */
545  	int
546  	pmExtractValue(int valfmt, const pmValue *ival, int itype,
547  				   pmAtomValue *oval, int otype)
548  	{
549  	    pmAtomValue	*ap;
550  	    pmAtomValue	av;
551  	    int		sts = 0;
552  	    int		len;
553  	    const char	*vp;
554  	    static char	buf[80];
555  	
556  	#ifdef PCP_DEBUG
557  	    if (pmDebug & DBG_TRACE_VALUE) {
558  		fprintf(stderr, "pmExtractValue: ");
559  		vp = "???";
560  	    }
561  	#endif
562  	
563  	    oval->ll = 0;
564  	    if (valfmt == PM_VAL_INSITU) {
565  		av.l = ival->value.lval;
566  	#ifdef PCP_DEBUG
567  		if (pmDebug & DBG_TRACE_VALUE)
568  		    vp = pmAtomStr(&av, itype);
569  	#endif
570  		switch (itype) {
571  	
572  		    case PM_TYPE_32:
573  		    case PM_TYPE_UNKNOWN:
574  			switch (otype) {
575  			    case PM_TYPE_32:
576  				oval->l = av.l;
577  				break;
578  			    case PM_TYPE_U32:
579  				if (av.l < 0)
580  				    sts = PM_ERR_SIGN;
581  				else
582  				    oval->ul = (__uint32_t)av.l;
583  				break;
584  			    case PM_TYPE_64:
585  				oval->ll = (__int64_t)av.l;
586  				break;
587  			    case PM_TYPE_U64:
588  				if (av.l < 0)
589  				    sts = PM_ERR_SIGN;
590  				else
591  				    oval->ull = (__uint64_t)av.l;
592  				break;
593  			    case PM_TYPE_FLOAT:
594  				oval->f = (float)av.l;
595  				break;
596  			    case PM_TYPE_DOUBLE:
597  				oval->d = (double)av.l;
598  				break;
599  			    default:
600  				sts = PM_ERR_CONV;
601  			}
602  			break;
603  	
604  		    case PM_TYPE_U32:
605  			switch (otype) {
606  			    case PM_TYPE_32:
607  				if (av.ul > 0x7fffffff)
608  				    sts = PM_ERR_TRUNC;
609  				else
610  				    oval->l = (__int32_t)av.ul;
611  				break;
612  			    case PM_TYPE_U32:
613  				oval->ul = (__uint32_t)av.ul;
614  				break;
615  			    case PM_TYPE_64:
616  				oval->ll = (__int64_t)av.ul;
617  				break;
618  			    case PM_TYPE_U64:
619  				oval->ull = (__uint64_t)av.ul;
620  				break;
621  			    case PM_TYPE_FLOAT:
622  				oval->f = (float)av.ul;
623  				break;
624  			    case PM_TYPE_DOUBLE:
625  				oval->d = (double)av.ul;
626  				break;
627  			    default:
628  				sts = PM_ERR_CONV;
629  			}
630  			break;
631  	
632  		    /*
633  		     * Notes on conversion to FLOAT ... because of the limited
634  		     * precision of the mantissa, more than one integer value
635  		     * maps to the same floating point value ... hence the
636  		     * >= (float)max-int-value style of tests
637  		     */
638  		    case PM_TYPE_FLOAT:		/* old style insitu encoding */
639  			switch (otype) {
640  			    case PM_TYPE_32:
641  				if ((float)ABS(av.f) >= (float)0x7fffffff)
642  				    sts = PM_ERR_TRUNC;
643  				else
644  				    oval->l = (__int32_t)av.f;
645  				break;
646  			    case PM_TYPE_U32:
647  				if (av.f >= (float)((unsigned)0xffffffff))
648  				    sts = PM_ERR_TRUNC;
649  				else if (av.f < 0)
650  				    sts = PM_ERR_SIGN;
651  				else
652  				    oval->ul = (__uint32_t)av.f;
653  				break;
654  			    case PM_TYPE_64:
655  	#if defined(HAVE_CONST_LONGLONG)
656  				if (av.f >= (float)0x7fffffffffffffffLL)
657  				    sts = PM_ERR_TRUNC;
658  	#else
659  				if (av.f >= (float)0x7fffffffffffffff)
660  				    sts = PM_ERR_TRUNC;
661  	#endif
662  				else
663  				    oval->ll = (__int64_t)av.f;
664  				break;
665  			    case PM_TYPE_U64:
666  	#if defined(HAVE_CONST_LONGLONG)
667  				if (av.f >= (float)((__uint64_t)0xffffffffffffffffLL))
668  				    sts = PM_ERR_TRUNC;
669  	#else
670  				if (av.f >= (float)((__uint64_t)0xffffffffffffffff))
671  				    sts = PM_ERR_TRUNC;
672  	#endif
673  				else if (av.f < 0)
674  				    sts = PM_ERR_SIGN;
675  				else
676  				    oval->ull = (__uint64_t)av.f;
677  				break;
678  			    case PM_TYPE_FLOAT:
679  				oval->f = av.f;
680  				break;
681  			    case PM_TYPE_DOUBLE:
682  				oval->d = (double)av.f;
683  				break;
684  			    default:
685  				sts = PM_ERR_CONV;
686  			}
687  			break;
688  	
689  		    case PM_TYPE_64:
690  		    case PM_TYPE_U64:
691  		    case PM_TYPE_DOUBLE:
692  		    case PM_TYPE_STRING:
693  		    case PM_TYPE_AGGREGATE:
694  		    case PM_TYPE_EVENT:
695  		    default:
696  			sts = PM_ERR_CONV;
697  		}
698  	    }
699  	    else if (valfmt == PM_VAL_DPTR || valfmt == PM_VAL_SPTR) {
700  		__int64_t	src;
701  		__uint64_t	usrc;
702  		double		dsrc;
703  		float		fsrc;
704  		switch (itype) {
705  	
706  		    case PM_TYPE_64:
707  			if (ival->value.pval->vlen != PM_VAL_HDR_SIZE + sizeof(__int64_t) ||
708  			    (ival->value.pval->vtype != PM_TYPE_64 &&
709  			     ival->value.pval->vtype != 0)) {
710  			    sts = PM_ERR_CONV;
711  			    break;
712  			}
713  			ap = (pmAtomValue *)&ival->value.pval->vbuf;
714  	#ifdef PCP_DEBUG
715  			if (pmDebug & DBG_TRACE_VALUE)
716  			    vp = pmAtomStr(ap, itype);
717  	#endif
718  			memcpy((void *)&src, (void *)ap, sizeof(src));
719  			switch (otype) {
720  			    case PM_TYPE_32:
721  				if (src > 0x7fffffff)
722  				    sts = PM_ERR_TRUNC;
723  				else
724  				    oval->l = (__int32_t)src;
725  				break;
726  			    case PM_TYPE_U32:
727  				if (src > (unsigned)0xffffffff)
728  				    sts = PM_ERR_TRUNC;
729  				else if (src < 0)
730  				    sts = PM_ERR_SIGN;
731  				else
732  				    oval->ul = (__uint32_t)src;
733  				break;
734  			    case PM_TYPE_64:
735  				oval->ll = src;
736  				break;
737  			    case PM_TYPE_U64:
738  				if (src < 0)
739  				    sts = PM_ERR_SIGN;
740  				else
741  				    oval->ull = (__uint64_t)src;
742  				break;
743  			    case PM_TYPE_FLOAT:
744  				oval->f = (float)src;
745  				break;
746  			    case PM_TYPE_DOUBLE:
747  				oval->d = (double)src;
748  				break;
749  			    default:
750  				sts = PM_ERR_CONV;
751  			}
752  			break;
753  	
754  		    case PM_TYPE_U64:
755  			if (ival->value.pval->vlen != PM_VAL_HDR_SIZE + sizeof(__uint64_t) ||
756  			    (ival->value.pval->vtype != PM_TYPE_U64 &&
757  			     ival->value.pval->vtype != 0)) {
758  			    sts = PM_ERR_CONV;
759  			    break;
760  			}
761  			ap = (pmAtomValue *)&ival->value.pval->vbuf;
762  	#ifdef PCP_DEBUG
763  			if (pmDebug & DBG_TRACE_VALUE)
764  			    vp = pmAtomStr(ap, itype);
765  	#endif
766  			memcpy((void *)&usrc, (void *)ap, sizeof(usrc));
767  			switch (otype) {
768  			    case PM_TYPE_32:
769  				if (usrc > 0x7fffffff)
770  				    sts = PM_ERR_TRUNC;
771  				else
772  				    oval->l = (__int32_t)usrc;
773  				break;
774  			    case PM_TYPE_U32:
775  				if (usrc > (unsigned)0xffffffff)
776  				    sts = PM_ERR_TRUNC;
777  				else
778  				    oval->ul = (__uint32_t)usrc;
779  				break;
780  			    case PM_TYPE_64:
781  	#if defined(HAVE_CONST_LONGLONG)
782  				if (usrc > (__int64_t)0x7fffffffffffffffLL)
783  				    sts = PM_ERR_TRUNC;
784  	#else
785  				if (usrc > (__int64_t)0x7fffffffffffffff)
786  				    sts = PM_ERR_TRUNC;
787  	#endif
788  				else
789  				    oval->ll = (__int64_t)usrc;
790  				break;
791  			    case PM_TYPE_U64:
792  				oval->ull = usrc;
793  				break;
794  			    case PM_TYPE_FLOAT:
795  	#if !defined(HAVE_CAST_U64_DOUBLE)
796  				if (SIGN_64_MASK & usrc)
797  				    oval->f = (float)(__int64_t)(usrc & (~SIGN_64_MASK)) + (__uint64_t)SIGN_64_MASK;
798  				else
799  				    oval->f = (float)(__int64_t)usrc;
800  	#else
801  				oval->f = (float)usrc;
802  	#endif
803  				break;
804  			    case PM_TYPE_DOUBLE:
805  	#if !defined(HAVE_CAST_U64_DOUBLE)
806  				if (SIGN_64_MASK & usrc)
807  				    oval->d = (double)(__int64_t)(usrc & (~SIGN_64_MASK)) + (__uint64_t)SIGN_64_MASK;
808  				else
809  				    oval->d = (double)(__int64_t)usrc;
810  	#else
811  				oval->d = (double)usrc;
812  	#endif
813  				break;
814  			    default:
815  				sts = PM_ERR_CONV;
816  			}
817  			break;
818  	
819  		    case PM_TYPE_DOUBLE:
820  			if (ival->value.pval->vlen != PM_VAL_HDR_SIZE + sizeof(double) ||
821  			    (ival->value.pval->vtype != PM_TYPE_DOUBLE &&
822  			     ival->value.pval->vtype != 0)) {
823  			    sts = PM_ERR_CONV;
824  			    break;
825  			}
826  			ap = (pmAtomValue *)&ival->value.pval->vbuf;
827  	#ifdef PCP_DEBUG
828  			if (pmDebug & DBG_TRACE_VALUE)
829  			    vp = pmAtomStr(ap, itype);
830  	#endif
831  			memcpy((void *)&dsrc, (void *)ap, sizeof(dsrc));
832  			switch (otype) {
833  			    case PM_TYPE_32:
834  				if (ABS(dsrc) >= (double)0x7fffffff)
835  				    sts = PM_ERR_TRUNC;
836  				else
837  				    oval->l = (__int32_t)dsrc;
838  				break;
839  			    case PM_TYPE_U32:
840  				if (dsrc >= (double)((unsigned)0xffffffff))
841  				    sts = PM_ERR_TRUNC;
842  				else if (dsrc < 0)
843  				    sts = PM_ERR_SIGN;
844  				else
845  				    oval->ul = (__uint32_t)dsrc;
846  				break;
847  			    case PM_TYPE_64:
848  	#if defined(HAVE_CONST_LONGLONG)
849  				if (dsrc >= (double)0x7fffffffffffffffLL)
850  				    sts = PM_ERR_TRUNC;
851  	#else
852  				if (dsrc >= (double)0x7fffffffffffffff)
853  				    sts = PM_ERR_TRUNC;
854  	#endif
855  				else
856  				    oval->ll = (__int64_t)dsrc;
857  				break;
858  			    case PM_TYPE_U64:
859  	#if defined(HAVE_CONST_LONGLONG)
860  				if (dsrc >= (double)((__uint64_t)0xffffffffffffffffLL))
861  				    sts = PM_ERR_TRUNC;
862  	#else
863  				if (dsrc >= (double)((__uint64_t)0xffffffffffffffff))
864  				    sts = PM_ERR_TRUNC;
865  	#endif
866  				else if (dsrc < 0)
867  				    sts = PM_ERR_SIGN;
868  				else
869  				    oval->ull = (__uint64_t)dsrc;
870  				break;
871  			    case PM_TYPE_FLOAT:
872  				oval->f = (float)dsrc;
873  				break;
874  			    case PM_TYPE_DOUBLE:
875  				oval->d = dsrc;
876  				break;
877  			    default:
878  				sts = PM_ERR_CONV;
879  			}
880  			break;
881  	
882  		    case PM_TYPE_FLOAT:		/* new style pmValueBlock encoding */
883  			if (ival->value.pval->vlen != PM_VAL_HDR_SIZE + sizeof(float) ||
884  			    (ival->value.pval->vtype != PM_TYPE_FLOAT &&
885  			     ival->value.pval->vtype != 0)) {
886  			    sts = PM_ERR_CONV;
887  			    break;
888  			}
889  			ap = (pmAtomValue *)&ival->value.pval->vbuf;
890  	#ifdef PCP_DEBUG
891  			if (pmDebug & DBG_TRACE_VALUE)
892  			    vp = pmAtomStr(ap, itype);
893  	#endif
894  			memcpy((void *)&fsrc, (void *)ap, sizeof(fsrc));
895  			switch (otype) {
896  			    case PM_TYPE_32:
897  				if ((float)ABS(fsrc) >= (float)0x7fffffff)
898  				    sts = PM_ERR_TRUNC;
899  				else
900  				    oval->l = (__int32_t)fsrc;
901  				break;
902  			    case PM_TYPE_U32:
903  				if (fsrc >= (float)((unsigned)0xffffffff))
904  				    sts = PM_ERR_TRUNC;
905  				else if (fsrc < 0)
906  				    sts = PM_ERR_SIGN;
907  				else
908  				    oval->ul = (__uint32_t)fsrc;
909  				break;
910  			    case PM_TYPE_64:
911  	#if defined(HAVE_CONST_LONGLONG)
912  				if (fsrc >= (float)0x7fffffffffffffffLL)
913  				    sts = PM_ERR_TRUNC;
914  	#else
915  				if (fsrc >= (float)0x7fffffffffffffff)
916  				    sts = PM_ERR_TRUNC;
917  	#endif
918  				else
919  				    oval->ll = (__int64_t)fsrc;
920  				break;
921  			    case PM_TYPE_U64:
922  	#if defined(HAVE_CONST_LONGLONG)
923  				if (fsrc >= (float)((__uint64_t)0xffffffffffffffffLL))
924  				    sts = PM_ERR_TRUNC;
925  	#else
926  				if (fsrc >= (float)((__uint64_t)0xffffffffffffffff))
927  				    sts = PM_ERR_TRUNC;
928  	#endif
929  				else if (fsrc < 0)
930  				    sts = PM_ERR_SIGN;
931  				else
932  				    oval->ull = (__uint64_t)fsrc;
933  				break;
934  			    case PM_TYPE_FLOAT:
935  				oval->f = fsrc;
936  				break;
937  			    case PM_TYPE_DOUBLE:
938  				oval->d = (float)fsrc;
939  				break;
940  			    default:
941  				sts = PM_ERR_CONV;
942  			}
943  			break;
944  	
945  		    case PM_TYPE_STRING:
946  			if (ival->value.pval->vtype != PM_TYPE_STRING &&
947  			    ival->value.pval->vtype != 0) {
948  			    sts = PM_ERR_CONV;
949  			    break;
950  			}
951  			len = ival->value.pval->vlen - PM_VAL_HDR_SIZE;
952  	#ifdef PCP_DEBUG
953  			if (pmDebug & DBG_TRACE_VALUE) {
Event array_null: Comparing an array to null is not useful: "ival->value.pval->vbuf == NULL".
954  			    if (ival->value.pval->vbuf == NULL)
955  				vp = "<null>";
956  			    else {
957  				int		i;
958  				i = (int)strlen(ival->value.pval->vbuf);
959  				if (i < 38)
960  				    snprintf(buf, sizeof(buf), "\"%s\"", ival->value.pval->vbuf);
961  				else
962  				    snprintf(buf, sizeof(buf), "\"%34.34s...\"", ival->value.pval->vbuf);
963  				vp = buf;
964  			    }
965  			}
966  	#endif
967  			if (otype != PM_TYPE_STRING) {
968  			    sts = PM_ERR_CONV;
969  			    break;
970  			}
971  			if ((oval->cp = (char *)malloc(len + 1)) == NULL) {
972  			    __pmNoMem("pmExtractValue.string", len + 1, PM_FATAL_ERR);
973  			}
974  			memcpy(oval->cp, ival->value.pval->vbuf, len);
975  			oval->cp[len] = '\0';
976  			break;
977  	
978  		    case PM_TYPE_AGGREGATE:
979  			if (ival->value.pval->vtype != PM_TYPE_AGGREGATE &&
980  			    ival->value.pval->vtype != 0) {
981  			    sts = PM_ERR_CONV;
982  			    break;
983  			}
984  			len = ival->value.pval->vlen;
985  	#ifdef PCP_DEBUG
986  			if (pmDebug & DBG_TRACE_VALUE) {
987  			    int		vlen;
988  			    int		i;
989  			    vlen = ival->value.pval->vlen - PM_VAL_HDR_SIZE;
990  			    if (vlen == 0)
991  				snprintf(buf, sizeof(buf), "[len=%d]", vlen);
992  			    else {
993  				char	*cp;
994  				char	*bp;
995  				snprintf(buf, sizeof(buf), "[len=%d]", vlen);
996  				cp = (char *)ival->value.pval->vbuf;
997  				for (i = 0; i < vlen && i < 12; i++) {
998  				    bp = &buf[strlen(buf)];
999  				    if ((i % 4) == 0)
1000 					snprintf(bp, sizeof(buf) - (bp-buf), " %02x", *cp & 0xff);
1001 				    else
1002 					snprintf(bp, sizeof(buf) - (bp-buf), "%02x", *cp & 0xff);
1003 				    cp++;
1004 				}
1005 				if (vlen > 12) {
1006 				    bp = &buf[strlen(buf)];
1007 				    snprintf(bp, sizeof(buf) - (bp-buf), " ...");
1008 				}
1009 			    }
1010 			    vp = buf;
1011 			}
1012 	#endif
1013 			if (otype != PM_TYPE_AGGREGATE) {
1014 			    sts = PM_ERR_CONV;
1015 			    break;
1016 			}
1017 			if ((oval->vbp = (pmValueBlock *)malloc(len)) == NULL) {
1018 			    __pmNoMem("pmExtractValue.aggr", len, PM_FATAL_ERR);
1019 			}
1020 			memcpy(oval->vbp, ival->value.pval, len);
1021 			break;
1022 	
1023 		    case PM_TYPE_32:
1024 		    case PM_TYPE_U32:
1025 		    case PM_TYPE_EVENT:
1026 		    default:
1027 			sts = PM_ERR_CONV;
1028 		}
1029 	    }
1030 	    else
1031 		sts = PM_ERR_CONV;
1032 	
1033 	#ifdef PCP_DEBUG
1034 	    if (pmDebug & DBG_TRACE_VALUE) {
1035 		fprintf(stderr, " %s", vp);
1036 		fprintf(stderr, " [%s]", pmTypeStr(itype));
1037 		if (sts == 0)
1038 		    fprintf(stderr, " -> %s", pmAtomStr(oval, otype));
1039 		else
1040 		    fprintf(stderr, " -> Error: %s", pmErrStr(sts));
1041 		fprintf(stderr, " [%s]\n", pmTypeStr(otype));
1042 	    }
1043 	#endif
1044 	
1045 	    return sts;
1046 	}