Clean up a slew of warnings from gcc -Wall - mostly unused variables.
[gwave-svn.git] / spicefile / ss_hspice.c
blobefe07ad635b442740900039c1952212e9f13d6df
1 /*
2 * ss_hspice.c: HSPICE routines for SpiceStream
4 * Copyright (C) 1998-2002 Stephen G. Tell
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "ssintern.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <float.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
31 #include <config.h>
32 #include <glib.h>
33 #include "spicestream.h"
35 SpiceStream *sf_rdhdr_hspice(char *name, FILE *fp);
36 SpiceStream *sf_rdhdr_hsascii(char *name, FILE *fp);
37 SpiceStream *sf_rdhdr_hsbin(char *name, FILE *fp);
39 static int sf_readrow_hsascii(SpiceStream *sf, double *ivar, double *dvars);
40 static int sf_readrow_hsbin(SpiceStream *sf, double *ivar, double *dvars);
41 static SpiceStream *hs_process_header(int nauto, int nprobe,
42 int nsweepparam, char *line, char *name);
43 static int sf_readsweep_hsascii(SpiceStream *sf, double *svar);
44 static int sf_readsweep_hsbin(SpiceStream *sf, double *svar);
45 static int sf_readblock_hsbin(FILE *fp, char **bufp, int *bufsize, int offset);
47 struct hsblock_header { /* structure of binary tr0 block headers */
48 gint32 h1;
49 gint32 h2;
50 gint32 h3;
51 gint32 block_nbytes;
54 union gint32bytes {
55 gint32 i;
56 gchar b[4];
59 static void swap_gint32(gint32 *pi, size_t n);
61 /* Read spice-type file header - autosense hspice binary or ascii */
62 SpiceStream *
63 sf_rdhdr_hspice(char *name, FILE *fp)
65 int c;
66 if((c = getc(fp)) == EOF)
67 return NULL;
68 ungetc(c, fp);
70 if((c & 0xff) < ' ')
71 return sf_rdhdr_hsbin(name, fp);
72 else
73 return sf_rdhdr_hsascii(name, fp);
75 return NULL;
78 /* Read spice-type file header - hspice ascii */
79 SpiceStream *
80 sf_rdhdr_hsascii(char *name, FILE *fp)
82 SpiceStream *sf = NULL;
83 char *line = NULL;
84 int nauto, nprobe, nsweepparam, ntables;
85 int lineno = 0;
86 int linesize = 1024;
87 int lineused;
88 char lbuf[256];
89 char nbuf[16];
90 char *cp;
91 int maxlines;
93 if(fgets(lbuf, sizeof(lbuf), fp) == NULL)
94 return NULL;
95 lineno++;
97 /* version of post format */
98 if(strncmp(&lbuf[16], "9007", 4) != 0
99 && strncmp(&lbuf[16], "9601", 4) != 0)
100 return NULL;
101 strncpy(nbuf, &lbuf[0], 4);
102 nbuf[4] = 0;
103 nauto = atoi(nbuf);
105 strncpy(nbuf, &lbuf[4], 4);
106 nbuf[4] = 0;
107 nprobe = atoi(nbuf);
109 strncpy(nbuf, &lbuf[8], 4);
110 nbuf[4] = 0;
111 nsweepparam = atoi(nbuf);
113 if(fgets(lbuf, sizeof(lbuf), fp) == NULL) /* date, time etc. */
114 return NULL;
115 lineno++;
116 /* number of sweeps, possibly with cruft at the start of the line */
117 if(fgets(lbuf, sizeof(lbuf), fp) == NULL)
118 return NULL;
119 cp = strchr(lbuf, ' ');
120 if(!cp)
121 cp = lbuf;
122 ntables = atoi(cp);
123 if(ntables == 0)
124 ntables = 1;
125 lineno++;
127 maxlines = nauto + nprobe + nsweepparam + 100;
128 /* lines making up a fixed-field structure with variable-types and
129 * variable names.
130 * variable names can get split across lines! so we remove newlines,
131 * paste all of the lines together, and then deal with the
132 * whole header at once.
133 * A variable name of "$&%#" indicates the end!
135 line = g_new0(char, linesize);
136 lineused = 0;
137 do {
138 int len;
139 if(fgets(lbuf, sizeof(lbuf), fp) == NULL)
140 return NULL;
141 lineno++;
142 if((cp = strchr(lbuf, '\n')) != NULL)
143 *cp = 0;
144 len = strlen(lbuf);
145 if(lineused + len + 1 > linesize) {
146 linesize *= 2;
147 if(linesize > 1050000) {
148 ss_msg(ERR, "rdhdr_ascii", "internal error - failed to find end of header\n; linesize=%d line=\n%.200s\n", linesize, line);
149 exit(4);
152 line = g_realloc(line, linesize);
154 strcat(line, lbuf);
155 lineused += len;
157 } while(!strstr(line, "$&%#") && lineno < maxlines);
158 if(lineno == maxlines) {
159 ss_msg(DBG, "rdhdr_hsascii", "%s:%d: end of hspice header not found", name,lineno);
160 goto fail;
163 sf = hs_process_header(nauto, nprobe, nsweepparam, line, name);
164 if(!sf)
165 goto fail;
166 sf->fp = fp;
167 sf->readrow = sf_readrow_hsascii;
168 sf->linebuf = line;
169 sf->linep = NULL;
170 sf->lbufsize = linesize;
171 sf->ntables = ntables;
172 sf->read_tables = 0;
173 sf->read_rows = 0;
174 sf->read_sweepparam = 0;
175 sf->readsweep = sf_readsweep_hsascii;
176 sf->lineno = lineno;
178 ss_msg(DBG, "rdhdr_hsascii", "ntables=%d; expect %d columns",
179 sf->ntables, sf->ncols);
181 return sf;
183 fail:
184 if(line)
185 g_free(line);
186 return NULL;
190 /* Read spice-type file header - hspice binary */
191 SpiceStream *
192 sf_rdhdr_hsbin(char *name, FILE *fp)
195 SpiceStream *sf = NULL;
196 char *ahdr = NULL;
197 int ahdrsize = 0;
198 int ahdrend = 0;
199 int n;
200 int datasize;
201 int nauto, nprobe, nsweepparam, ntables;
202 char nbuf[16];
203 struct hsblock_header hh;
205 do {
206 n = sf_readblock_hsbin(fp, &ahdr, &ahdrsize, ahdrend);
207 if(n <= 0)
208 goto fail;
209 ahdrend += n;
210 ahdr[ahdrend] = '\0';
212 } while(!strstr(ahdr, "$&%#"));
214 /* ahdr is an ascii header that describes the variables in
215 * much the same way that the first lines of the ascii format do,
216 * except that there are no newlines
219 if(strncmp(&ahdr[16], "9007", 4) != 0 /* version of post format */
220 && strncmp(&ahdr[16], "9601", 4) != 0)
221 goto fail;
222 strncpy(nbuf, &ahdr[0], 4);
223 nbuf[4] = 0;
224 nauto = atoi(nbuf); /* number of automaticly-included variables,
225 first one is independent variable */
226 strncpy(nbuf, &ahdr[4], 4);
227 nbuf[4] = 0;
228 nprobe = atoi(nbuf); /* number of user-requested columns */
230 strncpy(nbuf, &ahdr[8], 4);
231 nbuf[4] = 0;
232 nsweepparam = atoi(nbuf); /* number of sweep parameters */
234 ntables = atoi(&ahdr[176]);
235 if(ntables == 0)
236 ntables = 1;
238 sf = hs_process_header(nauto, nprobe, nsweepparam, &ahdr[256], name);
239 if(!sf)
240 goto fail;
242 if(fread(&hh, sizeof(hh), 1, fp) != 1) {
243 ss_msg(DBG, "sf_rdhdr_hsbin", "EOF reading block header");
244 goto fail;
246 if(hh.h1 == 0x04000000 && hh.h3 == 0x04000000) {
247 /* detected endian swap */
248 sf->flags |= SSF_ESWAP;
249 swap_gint32((gint32*)&hh, sizeof(hh)/sizeof(gint32));
251 if(hh.h1 != 4 || hh.h3 != 4) {
252 ss_msg(DBG, "sf_rdhdr_hsbin", "unexepected values in data block header");
253 goto fail;
256 datasize = hh.block_nbytes;
257 sf->expected_vals = datasize / sizeof(float);
258 sf->read_vals = 0;
260 ss_msg(DBG, "sf_rdhdr_hsbin", "datasize=%d expect %d columns, %d values;\n reading first data block at 0x%lx", datasize, sf->ncols, sf->expected_vals, (long)ftello64(fp));
263 sf->fp = fp;
264 sf->readrow = sf_readrow_hsbin;
265 sf->readsweep = sf_readsweep_hsbin;
267 sf->ntables = ntables;
268 sf->read_tables = 0;
269 sf->read_rows = 0;
270 sf->read_sweepparam = 0;
272 return sf;
273 fail:
274 if(ahdr)
275 g_free(ahdr);
276 if(sf) {
277 if(sf->dvar)
278 g_free(sf->dvar);
279 g_free(sf);
282 return NULL;
285 /* common code for reading ascii or binary hspice headers.
286 * Given a string of ascii header information, set up the
287 * SpiceStream structure appropriately.
288 * Returns NULL on failure.
290 static SpiceStream *
291 hs_process_header(int nauto, int nprobe, int nsweepparam, char *line, char *name)
293 char *cp;
294 char *signam;
295 SpiceStream *sf;
296 int i;
297 int hstype;
299 /* type of independent variable */
300 cp = strtok(line, " \t\n");
301 if(!cp) {
302 ss_msg(DBG, "hs_process_header", "%s: initial vartype not found on header line.", name);
303 return NULL;
305 sf = ss_new(NULL, name, nauto-1 + nprobe, nsweepparam);
306 hstype = atoi(cp);
307 switch(hstype) {
308 case 1:
309 sf->ivar->type = TIME;
310 break;
311 case 2:
312 sf->ivar->type = FREQUENCY;
313 break;
314 case 3:
315 sf->ivar->type = VOLTAGE;
316 break;
317 default:
318 sf->ivar->type = UNKNOWN;
319 break;
321 sf->ivar->col = 0;
322 sf->ivar->ncols = 1;
323 sf->ncols = 1;
325 /* dependent variable types */
326 for(i = 0; i < sf->ndv; i++) {
327 cp = strtok(NULL, " \t\n");
328 if(!cp) {
329 ss_msg(DBG, "hs_process_header", "%s: not enough vartypes on header line", name);
330 return NULL;
332 if(!isdigit(cp[0])) {
333 ss_msg(DBG, "hs_process_header", "%s: bad vartype %d [%s] on header line", name, i, cp);
334 return NULL;
336 hstype = atoi(cp);
337 switch(hstype) {
338 case 1:
339 case 2:
340 sf->dvar[i].type = VOLTAGE;
341 break;
342 case 8:
343 case 15:
344 case 22:
345 sf->dvar[i].type = CURRENT;
346 break;
347 default:
348 sf->dvar[i].type = UNKNOWN;
349 break;
352 /* how many columns comprise this variable? */
353 sf->dvar[i].col = sf->ncols;
354 if(i < nauto-1 && sf->ivar->type == FREQUENCY) {
355 sf->dvar[i].ncols = 2;
356 } else {
357 sf->dvar[i].ncols = 1;
359 sf->ncols += sf->dvar[i].ncols;
362 /* independent variable name */
363 signam = strtok(NULL, " \t\n");
364 if(!signam) {
365 ss_msg(DBG, "hs_process_header", "%s: no IV name found on header line", name);
366 goto fail;
368 sf->ivar->name = g_strdup(signam);
370 /* dependent variable names */
371 for(i = 0; i < sf->ndv; i++) {
372 if((signam = strtok(NULL, " \t\n")) == NULL) {
373 ss_msg(DBG, "hs_process_header", "%s: not enough DV names found on header line", name);
374 goto fail;
376 sf->dvar[i].name = g_strdup(signam);
378 /* sweep parameter names */
379 for(i = 0; i < sf->nsweepparam; i++) {
380 if((signam = strtok(NULL, " \t\n")) == NULL) {
381 ss_msg(DBG, "hs_process_header", "%s: not enough sweep parameter names found on header line", name);
382 goto fail;
384 sf->spar[i].name = g_strdup(signam);
387 return sf;
389 fail:
390 ss_delete(sf);
391 return NULL;
395 * Read a "block" from an HSPICE binary file.
396 * Returns number of bytes read, 0 for EOF, negative for error.
397 * The body of the block is copied into the buffer pointed to by the
398 * buffer-pointer pointed to by bufp, at offset offset.
399 * The buffer is expanded with g_realloc if necessary.
400 * If bufp is NULL, a new buffer is allocated. The buffer
401 * size is maintained in the int pointed to by bufsize.
404 static int
405 sf_readblock_hsbin(FILE *fp, char **bufp, int *bufsize, int offset)
407 struct hsblock_header hh;
408 gint32 trailer;
409 int eswap = 0;
411 if(fread(&hh, sizeof(hh), 1, fp) != 1) {
412 ss_msg(DBG, "sf_readblock_hsbin", "EOF reading block header");
413 return 0;
415 if(hh.h1 == 0x04000000 && hh.h3 == 0x04000000) {
416 /* detected endian swap */
417 eswap = 1;
418 swap_gint32((gint32*)&hh, sizeof(hh)/sizeof(gint32));
420 if(hh.h1 != 0x00000004 || hh.h3 != 0x00000004) {
421 ss_msg(DBG, "sf_readblock_hsbin", "unexepected values in block header");
422 return -1;
424 if(bufp == NULL) { /* new buffer: exact fit */
425 *bufsize = hh.block_nbytes;
426 *bufp = g_new(char, *bufsize);
429 /* need to expand: double buffer size or make room for two blocks
430 * this size, whichever is larger. Better to realloc more now and
431 * cut down on the number of future reallocs.
433 if(*bufsize < offset + hh.block_nbytes) {
434 if(2 * *bufsize > (*bufsize + 2 * hh.block_nbytes))
435 *bufsize *= 2;
436 else
437 *bufsize += 2 * hh.block_nbytes;
438 *bufp = g_realloc(*bufp, *bufsize);
440 if(fread(*bufp + offset, sizeof(char), hh.block_nbytes, fp) != hh.block_nbytes) {
441 ss_msg(DBG, "sf_readblock_hsbin", "EOF reading block body");
442 return 0;
444 if(fread(&trailer, sizeof(gint32), 1, fp) != 1) {
445 ss_msg(DBG, "sf_readblock_hsbin", "EOF reading block trailer");
446 return 0;
448 if(eswap) {
449 swap_gint32(&trailer, 1);
451 if(trailer != hh.block_nbytes) {
452 ss_msg(DBG, "sf_readblock_hsbin", "block trailer mismatch");
453 return -2;
455 return hh.block_nbytes;
459 * helper routine: get next floating-point value from data part of binary
460 * hspice file. Handles the block-structure of hspice files; all blocks
461 * encountered are assumed to be data blocks. We don't use readblock_hsbin because
462 * some versions of hspice write very large blocks, which would require a
463 * very large buffer.
465 * Returns 0 on EOF, 1 on success, negative on error.
467 static int
468 sf_getval_hsbin(SpiceStream *sf, double *dval)
470 off64_t pos;
471 float val;
472 struct hsblock_header hh;
473 gint32 trailer;
475 if(sf->read_vals >= sf->expected_vals) {
476 pos = ftello64(sf->fp);
477 if(fread(&trailer, sizeof(gint32), 1, sf->fp) != 1) {
478 ss_msg(DBG, "sf_getval_hsbin", "EOF reading block trailer at offset 0x%lx", (long) pos);
479 return 0;
481 if(sf->flags & SSF_ESWAP) {
482 swap_gint32(&trailer, 1);
484 if(trailer != sf->expected_vals * sizeof(float)) {
485 ss_msg(DBG, "sf_getval_hsbin", "block trailer mismatch at offset 0x%lx", (long) pos);
486 return -2;
489 pos = ftello64(sf->fp);
490 if(fread(&hh, sizeof(hh), 1, sf->fp) != 1) {
491 ss_msg(DBG, "sf_getval_hsbin", "EOF reading block header at offset 0x%lx", (long) pos);
492 return 0;
494 if(hh.h1 == 0x04000000 && hh.h3 == 0x04000000) {
495 /* detected endian swap */
496 sf->flags |= SSF_ESWAP;
497 swap_gint32((gint32*)&hh, sizeof(hh)/sizeof(gint32));
498 } else {
499 sf->flags &= ~SSF_ESWAP;
501 if(hh.h1 != 0x00000004 || hh.h3 != 0x00000004) {
502 ss_msg(ERR, "sf_getval_hsbin", "unexepected values in block header at offset 0x%lx", pos);
503 return -1;
505 sf->expected_vals = hh.block_nbytes / sizeof(float);
506 sf->read_vals = 0;
508 if(fread(&val, sizeof(float), 1, sf->fp) != 1) {
509 pos = ftello64(sf->fp);
510 ss_msg(ERR, "sf_getval_hsbin", "unexepected EOF in data at offset 0x%lx", (long) pos);
511 return 0;
513 sf->read_vals++;
515 if(sf->flags & SSF_ESWAP) {
516 swap_gint32((gint32 *)&val, 1);
518 *dval = val;
519 return 1;
523 * helper routine: get next value from ascii hspice file.
524 * the file is line-oriented, with fixed-width fields on each line.
525 * Lines may look like either of these two examples:
526 0.66687E-090.21426E+010.00000E+000.00000E+000.25000E+010.71063E-090.17877E+01
527 .00000E+00 .30000E+01 .30000E+01 .30000E+01 .30000E+01 .30000E+01 .30092E-05
528 * There may be whitespace at the end of the line before the newline.
530 * Returns 0 on EOF, 1 on success.
532 static int
533 sf_getval_hsascii(SpiceStream *sf, double *val)
535 char vbuf[16];
536 char *vp;
537 char *cp;
538 int l;
540 if(!sf->linep || (*sf->linep==0) || *sf->linep == '\n') {
541 if(fgets(sf->linebuf, sf->lbufsize, sf->fp) == NULL)
542 return 0;
544 l = strlen(sf->linebuf);
545 if(l) { /* delete whitespace at end of line */
546 cp = sf->linebuf + l - 1;
547 while(cp > sf->linebuf && *cp && isspace(*cp))
548 *cp-- = '\0';
550 sf->linep = sf->linebuf;
551 sf->line_length = strlen(sf->linep);
552 /* fprintf(stderr, "#line: \"%s\"\n", sf->linebuf); */
554 if(sf->linep > sf->linebuf + sf->line_length) {
555 ss_msg(WARN, "sf_getval_hsascii",
556 "%s: internal error or bad line in file", sf->filename);
557 return 0;
560 strncpy(vbuf, sf->linep, 11);
561 sf->linep += 11;
562 vbuf[11] = 0;
563 if(strlen(vbuf) != 11) {
564 /* incomplete float value - probably truncated or
565 partialy-written file */
566 return 0;
568 vp = vbuf;
569 while(isspace(*vp)) /* atof doesn't like spaces */
570 vp++;
571 *val = atof(vp);
572 /* fprintf(stderr, "#vp=\"%s\" val=%f\n", vp, *val); */
573 return 1;
576 /* Read row of values from ascii hspice-format file.
577 * Returns:
578 * 1 on success. also fills in *ivar scalar and *dvars vector
579 * 0 on EOF
580 * -1 on error (may change some ivar/dvar values)
581 * -2 on end of table, with more tables supposedly still to be read.
584 static int
585 sf_readrow_hsascii(SpiceStream *sf, double *ivar, double *dvars)
587 int i;
589 if(!sf->read_sweepparam) { /* first row of table */
590 if(sf_readsweep_hsascii(sf, NULL) <= 0) /* discard sweep parameters, if any */
591 return -1;
593 if(sf_getval_hsascii(sf, ivar) == 0)
594 return 0;
595 if(*ivar >= 1.0e29) { /* "infinity" at end of data table */
596 sf->read_tables++;
597 if(sf->read_tables == sf->ntables)
598 return 0; /* EOF */
599 else
600 sf->read_sweepparam = 0;
601 sf->read_rows = 0;
602 return -2; /* end of table, more tables follow */
605 sf->read_rows++;
606 for(i = 0; i < sf->ncols-1; i++) {
607 if(sf_getval_hsascii(sf, &dvars[i]) == 0) {
608 ss_msg(WARN, "sf_readrow_hsascii", "%s: EOF or error reading data field %d in row %d of table %d; file is incomplete.", sf->filename, i, sf->read_rows, sf->read_tables);
609 return 0;
612 return 1;
615 /* Read row of values from binary hspice-format file.
616 * Returns:
617 * 1 on success. also fills in *ivar scalar and *dvars vector
618 * 0 on EOF
619 * -1 on error (may change some ivar/dvar values)
621 static int
622 sf_readrow_hsbin(SpiceStream *sf, double *ivar, double *dvars)
624 int i;
625 int rc;
627 if(!sf->read_sweepparam) { /* first row of table */
628 if(sf_readsweep_hsbin(sf, NULL) <= 0) /* discard sweep parameters, if any */
629 return -1;
632 rc = sf_getval_hsbin(sf, ivar);
633 if(rc == 0) /* file EOF */
634 return 0;
635 if(rc < 0)
636 return -1;
637 if(*ivar >= 1.0e29) { /* "infinity" at end of data table */
638 sf->read_tables++;
639 if(sf->read_tables == sf->ntables)
640 return 0; /* end of data, should also be EOF but we don't check */
641 else {
642 sf->read_sweepparam = 0;
643 sf->read_rows = 0;
644 return -2; /* end of table, more tables follow */
647 sf->read_rows++;
648 for(i = 0; i < sf->ncols-1; i++) {
649 if(sf_getval_hsbin(sf, &dvars[i]) != 1) {
650 ss_msg(WARN, "sf_readrow_hsbin", "%s: EOF or error reading data field %d in row %d of table %d; file is incomplete.", sf->filename, i, sf->read_rows, sf->read_tables);
651 return 0;
654 return 1;
658 * Read the sweep parameters from an HSPICE ascii or binary file
659 * This routine must be called before the first sf_readrow_hsascii call in each data
660 * table. If it has not been called before the first readrow call, it will be called
661 * with a NULL svar pointer to read and discard the sweep data.
663 * returns:
664 * 1 on success
665 * -1 on error
667 static int
668 sf_readsweep_hsascii(SpiceStream *sf, double *svar)
670 int i;
671 double val;
672 for(i = 0; i < sf->nsweepparam; i++) {
673 if(sf_getval_hsascii(sf, &val) == 0) {
674 ss_msg(ERR, "sf_readsweep_hsascii", "unexpected EOF reading sweep parameters\n");
675 return -1;
677 if(svar)
678 svar[i] = val;
681 sf->read_sweepparam = 1;
682 return 1;
685 static int
686 sf_readsweep_hsbin(SpiceStream *sf, double *svar)
688 int i;
689 double val;
690 for(i = 0; i < sf->nsweepparam; i++) {
691 if(sf_getval_hsbin(sf, &val) != 1) {
692 ss_msg(ERR, "sf_readsweep_hsbin", "EOF or error reading sweep parameter\n");
693 return -1;
695 if(svar)
696 svar[i] = val;
699 sf->read_sweepparam = 1;
700 return 1;
705 * Estimate how many rows are in the file associated with sf.
706 * We base our estimate on the size of the file.
707 * This can be useful to aid in memory-use planning by programs planning to
708 * read the entire file.
710 * If the file descriptor is not associated with an ordinary file, we return 0
711 * to indicate that the length cannot be estimated.
712 * If an error occurs, -1 is returned.
714 static long
715 sf_guessrows_hsbin(SpiceStream *sf)
717 int rc;
718 struct stat st;
720 rc = fstat(fileno(sf->fp), &st);
721 if(rc < 0)
722 return -1;
723 if((st.st_mode & S_IFMT) != S_IFREG)
724 return 0;
726 return st.st_size / (sizeof(float) * sf->ncols);
730 static void
731 swap_gint32(gint32 *pi, size_t n)
733 union gint32bytes *p = (union gint32bytes *)pi;
734 size_t i;
735 gchar temp;
736 for(i = 0; i < n; i++) {
737 temp = p[i].b[3] ;
738 p[i].b[3] = p[i].b[0];
739 p[i].b[0] = temp;
741 temp = p[i].b[2] ;
742 p[i].b[2] = p[i].b[1];
743 p[i].b[1] = temp;