/* * blkcpy - general values and related routines used by the calculator * * Copyright (C) 1999-2007,2021-2023,2025 Landon Curt Noll and Ernest Bowen * * Primary author: Landon Curt Noll * * Calc is open software; you can redistribute it and/or modify it under * the terms of the version 2.1 of the GNU Lesser General Public License * as published by the Free Software Foundation. * * Calc is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * A copy of version 2.1 of the GNU Lesser General Public License is * distributed with calc under the filename COPYING-LGPL. You should have * received a copy with calc; if not, write to Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Under source code control: 1997/04/18 20:41:26 * File existed as early as: 1997 * * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ */ #include #include #include "calc.h" #include "alloc.h" #include "value.h" #include "file.h" #include "blkcpy.h" #include "str.h" #include "errtbl.h" #include "banned.h" /* include after system header <> includes */ /* * copystod - copy num indexed items from source value to destination value * * given: * ssi = source starting index * num = number of items (octets or values) to be copied * sdi = destination starting index * * returns: * zero if successful, otherwise error-code number */ int copystod(VALUE *svp, long ssi, long num, VALUE *dvp, long dsi) { BLOCK *sblk; BLOCK *dblk; bool noreloc; sblk = NULL; dblk = NULL; /* * check protections */ if (svp->v_subtype & V_NOCOPYFROM) return E_COPY_13; if (dvp->v_subtype & V_NOCOPYTO) return E_COPY_14; noreloc = ((dvp->v_subtype & V_NOREALLOC) != 0); /* * determine/check source type */ switch(svp->v_type) { case V_NBLOCK: if (svp->v_nblock->subtype & V_NOCOPYFROM) return E_COPY_15; sblk = svp->v_nblock->blk; if (sblk->data == NULL) return E_COPY_08; break; case V_BLOCK: sblk = svp->v_block; break; case V_STR: case V_OCTET: case V_NUM: case V_FILE: case V_MAT: case V_LIST: break; default: return E_COPY_09; } /* * determine/check destination type */ switch(dvp->v_type) { case V_NBLOCK: if (dvp->v_nblock->subtype & V_NOCOPYTO) return E_COPY_16; noreloc |=((dvp->v_nblock->subtype & V_NOREALLOC) != 0); dblk = dvp->v_nblock->blk; if (dblk->data == NULL) return E_COPY_10; break; case V_BLOCK: noreloc = ((dvp->v_subtype & V_NOREALLOC) != 0); dblk = dvp->v_block; break; case V_STR: case V_NUM: case V_FILE: case V_MAT: case V_LIST: break; default: return E_COPY_11; } /* * copy based on source */ switch (svp->v_type) { case V_BLOCK: case V_NBLOCK: /* * copy from a block */ switch(dvp->v_type) { case V_BLOCK: case V_NBLOCK: return copyblk2blk(sblk, ssi, num, dblk, dsi, noreloc); case V_NUM: { NUMBER *n; /* modified number */ int rt; /* return code */ /* copy to a number */ rt = copyblk2num(sblk, ssi, num, dvp->v_num, dsi, &n); if (rt == 0) { qfree(dvp->v_num); dvp->v_num = n; } return rt; } case V_FILE: return copyblk2file(sblk, ssi, num, dvp->v_file, dsi); case V_MAT: return copyblk2mat(sblk, ssi, num, dvp->v_mat, dsi); case V_STR: return copyblk2str(sblk, ssi, num, dvp->v_str, dsi); } return E_COPY_12; case V_STR: switch(dvp->v_type) { case V_BLOCK: case V_NBLOCK: /* copy to a block */ return copystr2blk(svp->v_str, ssi, num, dblk, dsi, noreloc); case V_FILE: return copystr2file(svp->v_str, ssi, num, dvp->v_file, dsi); case V_STR: return copystr2str(svp->v_str, ssi, num, dvp->v_str, dsi); } return E_COPY_12; case V_OCTET: switch(dvp->v_type) { case V_BLOCK: case V_NBLOCK: return copyostr2blk((char *) svp->v_octet, ssi, num, dblk, dsi, noreloc); case V_STR: return copyostr2str((char *) svp->v_octet, ssi, num, dvp->v_str, dsi); } return E_COPY_12; case V_NUM: /* * copy from a number */ if (dblk != NULL) { /* copy to a block */ return copynum2blk(svp->v_num, ssi, num, dblk, dsi, noreloc); } switch (dvp->v_type) { case V_MAT: /* copy to a matrix */ return E_COPY_12; /* not yet - XXX */ case V_LIST: /* copy to a list */ return E_COPY_12; /* not yet - XXX */ } break; case V_FILE: /* * copy from a file */ if (dblk != NULL) { /* copy to a block */ return copyfile2blk(svp->v_file, ssi, num, dblk, dsi, noreloc); } switch (dvp->v_type) { case V_NUM: /* copy to a number */ return E_COPY_12; /* not yet - XXX */ } break; case V_MAT: /* * copy from a matrix */ if (dblk != NULL) { /* copy to a block */ return copymat2blk(svp->v_mat, ssi, num, dblk, dsi, noreloc); } switch (dvp->v_type) { case V_MAT: /* copy to a matrix */ return copymat2mat(svp->v_mat, ssi, num, dvp->v_mat, dsi); case V_LIST: /* copy to a list */ return copymat2list(svp->v_mat, ssi, num, dvp->v_list, dsi); } break; case V_LIST: /* * copy from a list */ if (dblk != NULL) { /* copy to a block */ return E_COPY_12; /* not yet - XXX */ } switch (dvp->v_type) { case V_MAT: /* copy to a matrix */ return copylist2mat(svp->v_list, ssi, num, dvp->v_mat, dsi); case V_LIST: /* copy to a list */ return copylist2list(svp->v_list, ssi, num, dvp->v_list, dsi); } break; } /* * unsupported copy combination */ return E_COPY_12; } /* * copymat2mat - copy matrix to matrix */ int copymat2mat(MATRIX *smat, long ssi, long num, MATRIX *dmat, long dsi) { long i; VALUE *vp; VALUE *vq; VALUE *vtemp; unsigned short subtype; if (ssi > smat->m_size) return E_COPY_02; if (num < 0) num = smat->m_size - ssi; if (ssi + num > smat->m_size) return E_COPY_05; if (num == 0) return 0; if (dsi < 0) dsi = 0; if (dsi + num > dmat->m_size) return E_COPY_07; vtemp = (VALUE *) malloc(num * sizeof(VALUE)); if (vtemp == NULL) { math_error("Out of memory for mat-to-mat copy"); not_reached(); } vp = smat->m_table + ssi; vq = vtemp; i = num; while (i-- > 0) copyvalue(vp++, vq++); vp = vtemp; vq = dmat->m_table + dsi; for (i = num; i > 0; i--, vp++, vq++) { subtype = vq->v_subtype; freevalue(vq); *vq = *vp; vq->v_subtype |= subtype; } free(vtemp); return 0; } /* * copyblk2mat - copy block to matrix */ int copyblk2mat(BLOCK *blk, long ssi, long num, MATRIX *dmat, long dsi) { OCTET *op; VALUE *vp; VALUE *vq; VALUE *vtemp; long i; unsigned short subtype; if (ssi > blk->datalen) return E_COPY_02; if (num < 0) num = blk->datalen - ssi; if (ssi + num > blk->datalen) return E_COPY_05; if (num == 0) return 0; if (dsi < 0) dsi = 0; if (dsi + num > dmat->m_size) return E_COPY_07; op = blk->data + ssi; vtemp = (VALUE *) malloc(num * sizeof(VALUE)); if (vtemp == NULL) { math_error("Out of memory for block-to-matrix copy"); not_reached(); } vp = vtemp; i = num; while (i-- > 0) { vp->v_type = V_NUM; vp->v_subtype = V_NOSUBTYPE; vp->v_num = itoq((long) *op++); vp++; } vp = vtemp; vq = dmat->m_table + dsi; for (i = num; i > 0; i--, vp++, vq++) { subtype = vq->v_subtype; freevalue(vq); *vq = *vp; vq->v_subtype |= subtype; } free(vtemp); return 0; } /* * copymat2blk - copy matrix to block */ int copymat2blk(MATRIX *smat, long ssi, long num, BLOCK *dblk, long dsi, bool noreloc) { long i; long newlen; long newsize; USB8 *newdata; VALUE *vp; OCTET *op; if (ssi > smat->m_size) return E_COPY_02; if (num < 0) num = smat->m_size - ssi; if (num == 0) return 0; if (ssi + num > smat->m_size) return E_COPY_05; if (dsi < 0) dsi = dblk->datalen; newlen = dsi + num; if (newlen <= 0) return E_COPY_07; if (newlen >= dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for matrix-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } vp = smat->m_table + ssi; op = dblk->data + dsi; for (i = num; i > 0; i--) copy2octet(vp++, op++); if (newlen > dblk->datalen) dblk->datalen = newlen; return 0; } /* * copymat2list - copy matrix to list */ int copymat2list(MATRIX *smat, long ssi, long num, LIST *lp, long dsi) { VALUE *vp; VALUE *vq; LISTELEM *ep; VALUE *vtemp; long i; unsigned short subtype; if (ssi > smat->m_size) return E_COPY_02; if (num < 0) num = smat->m_size - ssi; if (num == 0) return 0; if (ssi + num > smat->m_size) return E_COPY_05; if (dsi < 0) dsi = 0; if (dsi + num > lp->l_count) return E_COPY_07; vtemp = (VALUE *) malloc(num * sizeof(VALUE)); if (vtemp == NULL) { math_error("Out of memory for matrix-to-list copy"); not_reached(); } vp = smat->m_table + ssi; vq = vtemp; i = num; while (i-- > 0) copyvalue(vp++, vq++); vq = vtemp; ep = listelement(lp, (long) dsi); i = num; while (i-- > 0) { subtype = ep->e_value.v_subtype; freevalue(&ep->e_value); ep->e_value = *vq++; ep->e_value.v_subtype |= subtype; ep = ep->e_next; } free(vtemp); return 0; } /* * copymat2list - copy list to matrix */ int copylist2mat(LIST *lp, long ssi, long num, MATRIX *dmat, long dsi) { VALUE *vp; VALUE *vq; LISTELEM *ep; VALUE *vtemp; long i; unsigned short subtype; if (ssi > lp->l_count) return E_COPY_02; if (num < 0) num = lp->l_count - ssi; if (num == 0) return 0; if (ssi + num > lp->l_count) return E_COPY_05; if (dsi < 0) dsi = 0; if (dsi + num > dmat->m_size) return E_COPY_07; vtemp = (VALUE *) malloc(num * sizeof(VALUE)); if (vtemp == NULL) { math_error("Out of memory for list-to-matrix copy"); not_reached(); } ep = listelement(lp, (long) ssi); vp = vtemp; i = num; while (i-- > 0) { copyvalue(&ep->e_value, vp++); ep = ep->e_next; } vp = vtemp; vq = dmat->m_table + dsi; for (i = num; i > 0; i--, vp++, vq++) { subtype = vq->v_subtype; freevalue(vq); *vq = *vp; vq->v_subtype |= subtype; } free(vtemp); return 0; } /* * copylist2list - copy list to list */ int copylist2list(LIST *slp, long ssi, long num, LIST *dlp, long dsi) { long i; LISTELEM *sep; LISTELEM *dep; VALUE *vtemp; VALUE *vp; unsigned short subtype; if (ssi > slp->l_count) return E_COPY_02; if (num < 0) num = slp->l_count - ssi; if (num == 0) return 0; if (ssi + num > slp->l_count) return E_COPY_05; if (dsi < 0) dsi = 0; if (dsi + num > dlp->l_count) return E_COPY_07; vtemp = (VALUE *) malloc(num * sizeof(VALUE)); if (vtemp == NULL) { math_error("Out of memory for list-to-list copy"); not_reached(); } sep = listelement(slp, (long) ssi); vp = vtemp; i = num; while (i-- > 0) { copyvalue(&sep->e_value, vp++); sep = sep->e_next; } dep = listelement(dlp, (long) dsi); vp = vtemp; i = num; while (i-- > 0) { subtype = dep->e_value.v_subtype; freevalue(&dep->e_value); dep->e_value = *vp++; dep->e_value.v_subtype |= subtype; dep = dep->e_next; } free(vtemp); return 0; } /* * copyblk2file - copy block to file */ int copyblk2file(BLOCK *sblk, long ssi, long num, FILEID id, long dsi) { FILEIO *fiop; FILE *fp; long numw; if (ssi > sblk->datalen) return E_COPY_02; if (num < 0) num = sblk->datalen - ssi; if (num == 0) return 0; fiop = findid(id, true); if (fiop == NULL) return E_COPYF_1; fp = fiop->fp; if (id == 1 || id == 2) { numw = idfputstr(id, (char *)sblk->data + ssi); /* XXX */ return 0; } if (dsi >= 0) { if (fseek(fp, dsi, 0)) return E_COPYF_2; } numw = fwrite(sblk->data + ssi, 1, num, fp); if (numw < num) return E_COPYF_3; fflush(fp); return 0; } /* * copyfile2blk - copy file to block */ int copyfile2blk(FILEID id, long ssi, long num, BLOCK *dblk, long dsi, bool noreloc) { FILEIO *fiop; FILE *fp; long numw; ZVALUE fsize; long filelen; long newlen; long newsize; OCTET *newdata; if (id < 3) /* excludes copying from stdin */ return E_COPYF_1; fiop = findid(id, false); if (fiop == NULL) return E_COPYF_1; fp = fiop->fp; if (get_open_siz(fp, &fsize)) return E_COPYF_2; if (zge31b(fsize)) { zfree(fsize); return E_COPY_05; } filelen = ztoi(fsize); zfree(fsize); if (ssi > filelen) return E_COPY_02; if (num < 0) num = filelen - ssi; if (num == 0) return 0; if (ssi + num > filelen) return E_COPY_05; if (fseek(fp, ssi, 0)) /* using system fseek XXX */ return E_COPYF_2; if (dsi < 0) dsi = dblk->datalen; newlen = dsi + num; if (newlen <= 0) return E_COPY_07; if (newlen >= dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for block-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } numw = fread(dblk->data + dsi, 1, num, fp); if (numw < num) return E_COPYF_4; if (newlen > dblk->datalen) dblk->datalen = newlen; return 0; } /* * copystr2file - copy string to file */ int copystr2file(STRING *str, long ssi, long num, FILEID id, long dsi) { long len; FILEIO *fiop; long numw; FILE *fp; len = str->s_len; if (ssi >= len) return E_COPY_02; if (num < 0) num = len - ssi; if (num <= 0) /* Nothing to be copied */ return 0; if (ssi + num > len) return E_COPY_05; /* Insufficient memory in str */ fiop = findid(id, true); if (fiop == NULL) return E_COPYF_1; fp = fiop->fp; if (id == 1 || id == 2) { numw = idfputstr(id, str->s_str + ssi); /* XXX */ return 0; } if (dsi >= 0) { if (fseek(fp, dsi, 0)) return E_COPYF_2; } numw = fwrite(str->s_str + ssi, 1, num, fp); if (numw < num) return E_COPYF_3; fflush(fp); return 0; } /* * copyblk2blk - copy block to block */ int copyblk2blk(BLOCK *sblk, long ssi, long num, BLOCK *dblk, long dsi, bool noreloc) { long newlen; long newsize; USB8 *newdata; if (ssi > sblk->datalen) return E_COPY_02; if (num < 0) num = sblk->datalen - ssi; if (num == 0) /* Nothing to be copied */ return 0; if (ssi + num > sblk->datalen) return E_COPY_05; if (dsi < 0) dsi = dblk->datalen; newlen = dsi + num; if (newlen <= 0) return E_COPY_07; if (newlen >= dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for block-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } memmove(dblk->data + dsi, sblk->data + ssi, num); if (newlen > dblk->datalen) dblk->datalen = newlen; return 0; } /* * copystr2blk - copy string to block */ int copystr2blk(STRING *str, long ssi, long num, BLOCK *dblk, long dsi, bool noreloc) { long len; long newlen; long newsize; USB8 *newdata; len = str->s_len; if (ssi >= len) return E_COPY_02; if (num < 0) num = len - ssi; if (num <= 0) /* Nothing to be copied */ return 0; if (dsi < 0) dsi = dblk->datalen; newlen = dsi + num + 1; if (newlen <= 0) return E_COPY_07; if (newlen >= dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for string-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } memmove(dblk->data + dsi, str->s_str + ssi, num); dblk->data[dsi + num] = '\0'; if (newlen > dblk->datalen) dblk->datalen = newlen; return 0; } /* * copystr2str - copy up to num characters from sstr (starting at * index ssi) to dstr (starting at index dsi); num is reduced if there * are insufficient characters in sstr or insufficient space in dstr. */ int copystr2str(STRING *sstr, long ssi, long num, STRING *dstr, long dsi) { char *c, *c1; if (num < 0 || (size_t)(ssi + num) > sstr->s_len) num = sstr->s_len - ssi; if (num <= 0) return 0; /* Nothing to be copied */ if (dsi < 0) /* default destination index */ dsi = 0; if ((size_t)(dsi + num) > dstr->s_len) num = dstr->s_len - dsi; c1 = sstr->s_str + ssi; c = dstr->s_str + dsi; while (num-- > 0) *c++ = *c1++; return 0; } /* * copyblk2str - copy up to num characters from sblk (starting at * index ssi) to str (starting at index dsi); num is reduced if there * is insufficient data in blk or insufficient space in str */ int copyblk2str(BLOCK *sblk, long ssi, long num, STRING *dstr, long dsi) { USB8 *c, *c1; if (num < 0 || ssi + num > sblk->datalen) num = sblk->datalen - ssi; if (num <= 0) return 0; /* Nothing to be copied */ if (dsi < 0) /* default destination index */ dsi = 0; if ((size_t)(dsi + num) > dstr->s_len) num = dstr->s_len - dsi; c1 = sblk->data + ssi; c = (USB8 *)dstr->s_str + dsi; while (num-- > 0) *c++ = *c1++; return 0; } /* * copyostr2str - copy octet-specified string to string */ int copyostr2str(char *sstr, long ssi, long num, STRING *dstr, long dsi) { size_t len; char *c, *c1; len = strlen(sstr); if (num < 0 || (size_t)(ssi + num) > len) num = len - ssi; if (num <= 0) /* Nothing to be copied */ return 0; if (dsi < 0) dsi = 0; /* Default destination index */ if ((size_t)(dsi + num) > dstr->s_len) num = dstr->s_len - dsi; c1 = sstr + ssi; c = dstr->s_str + dsi; while (num-- > 0) *c++ = *c1++; return 0; } /* * copyostr2blk - copy octet-specified string to block */ int copyostr2blk(char *str,long ssi,long num,BLOCK *dblk,long dsi,bool noreloc) { size_t len; size_t newlen; size_t newsize; USB8 *newdata; len = strlen(str) + 1; if (ssi > 0 && (size_t)ssi > len) return E_COPY_02; if (num < 0 || (size_t)(ssi + num) > len) num = len - ssi; if (num <= 0) /* Nothing to be copied */ return 0; if (dsi < 0) dsi = dblk->datalen; /* Default destination index */ newlen = dsi + num; if (newlen <= 0) return E_COPY_07; if (newlen >= (size_t)dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for string-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } memmove(dblk->data + dsi, str + ssi, num); if (newlen > (size_t)dblk->datalen) dblk->datalen = newlen; return 0; } /* * copynum2blk - copy number numerator to block */ int copynum2blk(NUMBER *snum, long ssi, long num, BLOCK *dblk, long dsi, bool noreloc) { size_t newlen; size_t newsize; USB8 *newdata; #if CALC_BYTE_ORDER == BIG_ENDIAN ZVALUE *swnum; /* byte swapped numerator */ #endif if (ssi > snum->num.len) return E_COPY_02; if (num < 0) num = snum->num.len - ssi; if (num == 0) /* Nothing to be copied */ return 0; if (ssi + num > snum->num.len) return E_COPY_05; if (dsi < 0) dsi = dblk->datalen; newlen = dsi + (num*sizeof(HALF)); if (newlen <= 0) return E_COPY_07; if (newlen >= (size_t)dblk->maxsize) { if (noreloc) return E_COPY_17; newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk; newdata = (USB8*) realloc(dblk->data, newsize); if (newdata == NULL) { math_error("Out of memory for num-to-block copy"); not_reached(); } dblk->data = newdata; dblk->maxsize = newsize; } #if CALC_BYTE_ORDER == LITTLE_ENDIAN memmove(dblk->data+dsi, (char *)(snum->num.v+ssi), num*sizeof(HALF)); #else swnum = swap_b8_in_ZVALUE(NULL, &(snum->num), false); memmove(dblk->data+dsi, (char *)(swnum->v+ssi), num*sizeof(HALF)); zfree(*swnum); #endif if (newlen > (size_t)dblk->datalen) dblk->datalen = newlen; return 0; } /* * copyblk2num - copy block to number */ int copyblk2num(BLOCK *sblk, long ssi, long num, NUMBER *dnum, long dsi, NUMBER **res) { size_t newlen; NUMBER *ret; /* cloned and modified numerator */ #if CALC_BYTE_ORDER == BIG_ENDIAN HALF *swapped; /* byte swapped input data */ unsigned long halflen; /* length of the input rounded up to HALFs */ HALF *h; /* copy byteswap pointer */ unsigned long i; #endif if (ssi > sblk->datalen) return E_COPY_02; if (num < 0) num = sblk->datalen - ssi; if (num == 0) /* Nothing to be copied */ return 0; if (ssi + num > sblk->datalen) return E_COPY_05; if (dsi < 0) dsi = dnum->num.len; newlen = dsi + ((num+sizeof(HALF)-1)/sizeof(HALF)); if (newlen <= 0) return E_COPY_07; /* quasi-clone the numerator to the new size */ ret = qalloc(); ret->num.sign = dnum->num.sign; ret->num.v = alloc(newlen); ret->num.len = newlen; /* ensure that any trailing octets will be zero filled */ ret->num.v[newlen-1] = 0; zcopyval(dnum->num, ret->num); if (!zisunit(ret->den)) { ret->den.len = dnum->den.len; ret->den.v = alloc(dnum->den.len); zcopyval(dnum->den, ret->den); } /* move the data */ #if CALC_BYTE_ORDER == LITTLE_ENDIAN memmove((char *)(ret->num.v + dsi), sblk->data + ssi, num); #else /* form a HALF aligned copy of the input */ halflen = (num+sizeof(HALF)-1) / sizeof(HALF); swapped = (HALF *)malloc(halflen * sizeof(HALF)); if (swapped == NULL) { math_error("Out of memory for block-to-num copy"); not_reached(); } /* ensure that any trailing octets will be zero filled */ swapped[halflen-1] = 0; memcpy(swapped, sblk->data + ssi, num); /* byte swap the copy of the input */ for (i=0, h=swapped; i < halflen; ++i, ++h) { SWAP_B8_IN_HALF(h, h); } /* copy over whole byte-swapped HALFs */ memcpy((char *)(ret->num.v + dsi), swapped, (num/sizeof(HALF))*sizeof(HALF)); /* copy over any octets in the last partial HALF */ i = num % sizeof(HALF); if (i != 0) { memcpy((char *)(ret->num.v + dsi)+num-i, (char *)swapped + num-i, i); } free(swapped); #endif /* save new number */ *res = ret; return 0; }