mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Some folks might think: “you still use RCS”?!? And we will say, hey, at least we switched from SCCS to RCS back in … I think it was around 1994 ... at least we are keeping up! :-) :-) :-) Logs say that SCCS version 18 became RCS version 19 on 1994 March 18. RCS served us well. But now it is time to move on. And so we are switching to git. Calc releases produce a lot of file changes. In the 125 releases of calc since 1996, when I started managing calc releases, there have been 15473 file mods!
1109 lines
22 KiB
C
1109 lines
22 KiB
C
/*
|
|
* blkcpy - general values and related routines used by the calculator
|
|
*
|
|
* Copyright (C) 1999-2007 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 <stdio.h>
|
|
#include <sys/types.h>
|
|
#include "calc.h"
|
|
#include "value.h"
|
|
#include "file.h"
|
|
#include "blkcpy.h"
|
|
#include "str.h"
|
|
|
|
|
|
/*
|
|
* 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_COPY13;
|
|
if (dvp->v_subtype & V_NOCOPYTO)
|
|
return E_COPY14;
|
|
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_COPY15;
|
|
sblk = svp->v_nblock->blk;
|
|
if (sblk->data == NULL)
|
|
return E_COPY8;
|
|
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_COPY9;
|
|
}
|
|
|
|
/*
|
|
* determine/check destination type
|
|
*/
|
|
switch(dvp->v_type) {
|
|
case V_NBLOCK:
|
|
if (dvp->v_nblock->subtype & V_NOCOPYTO)
|
|
return E_COPY16;
|
|
noreloc |=((dvp->v_nblock->subtype & V_NOREALLOC) != 0);
|
|
dblk = dvp->v_nblock->blk;
|
|
if (dblk->data == NULL)
|
|
return E_COPY10;
|
|
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_COPY11;
|
|
}
|
|
|
|
/*
|
|
* 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_COPY12;
|
|
|
|
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_COPY12;
|
|
|
|
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_COPY12;
|
|
|
|
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_COPY12; /* not yet - XXX */
|
|
case V_LIST:
|
|
/* copy to a list */
|
|
return E_COPY12; /* 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_COPY12; /* 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_COPY12; /* 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_COPY12;
|
|
}
|
|
|
|
|
|
/*
|
|
* 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_COPY2;
|
|
|
|
if (num < 0)
|
|
num = smat->m_size - ssi;
|
|
if (ssi + num > smat->m_size)
|
|
return E_COPY5;
|
|
if (num == 0)
|
|
return 0;
|
|
if (dsi < 0)
|
|
dsi = 0;
|
|
if (dsi + num > dmat->m_size)
|
|
return E_COPY7;
|
|
vtemp = (VALUE *) malloc(num * sizeof(VALUE));
|
|
if (vtemp == NULL) {
|
|
math_error("Out of memory for mat-to-mat copy");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = blk->datalen - ssi;
|
|
if (ssi + num > blk->datalen)
|
|
return E_COPY5;
|
|
if (num == 0)
|
|
return 0;
|
|
if (dsi < 0)
|
|
dsi = 0;
|
|
if (dsi + num > dmat->m_size)
|
|
return E_COPY7;
|
|
op = blk->data + ssi;
|
|
vtemp = (VALUE *) malloc(num * sizeof(VALUE));
|
|
if (vtemp == NULL) {
|
|
math_error("Out of memory for block-to-matrix copy");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = smat->m_size - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
if (ssi + num > smat->m_size)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = dblk->datalen;
|
|
newlen = dsi + num;
|
|
if (newlen <= 0)
|
|
return E_COPY7;
|
|
if (newlen >= dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = smat->m_size - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
if (ssi + num > smat->m_size)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = 0;
|
|
if (dsi + num > lp->l_count)
|
|
return E_COPY7;
|
|
vtemp = (VALUE *) malloc(num * sizeof(VALUE));
|
|
if (vtemp == NULL) {
|
|
math_error("Out of memory for matrix-to-list copy");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = lp->l_count - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
if (ssi + num > lp->l_count)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = 0;
|
|
if (dsi + num > dmat->m_size)
|
|
return E_COPY7;
|
|
vtemp = (VALUE *) malloc(num * sizeof(VALUE));
|
|
if (vtemp == NULL) {
|
|
math_error("Out of memory for list-to-matrix copy");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = slp->l_count - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
if (ssi + num > slp->l_count)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = 0;
|
|
if (dsi + num > dlp->l_count)
|
|
return E_COPY7;
|
|
vtemp = (VALUE *) malloc(num * sizeof(VALUE));
|
|
if (vtemp == NULL) {
|
|
math_error("Out of memory for list-to-list copy");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = sblk->datalen - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
|
|
fiop = findid(id, TRUE);
|
|
if (fiop == NULL)
|
|
return E_COPYF1;
|
|
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_COPYF2;
|
|
}
|
|
numw = fwrite(sblk->data + ssi, 1, num, fp);
|
|
if (numw < num)
|
|
return E_COPYF3;
|
|
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_COPYF1;
|
|
fiop = findid(id, FALSE);
|
|
if (fiop == NULL)
|
|
return E_COPYF1;
|
|
|
|
fp = fiop->fp;
|
|
|
|
if (get_open_siz(fp, &fsize))
|
|
return E_COPYF2;
|
|
if (zge31b(fsize)) {
|
|
zfree(fsize);
|
|
return E_COPY5;
|
|
}
|
|
filelen = ztoi(fsize);
|
|
zfree(fsize);
|
|
|
|
if (ssi > filelen)
|
|
return E_COPY2;
|
|
if (num < 0)
|
|
num = filelen - ssi;
|
|
if (num == 0)
|
|
return 0;
|
|
if (ssi + num > filelen)
|
|
return E_COPY5;
|
|
if (fseek(fp, ssi, 0)) /* using system fseek XXX */
|
|
return E_COPYF2;
|
|
if (dsi < 0)
|
|
dsi = dblk->datalen;
|
|
newlen = dsi + num;
|
|
if (newlen <= 0)
|
|
return E_COPY7;
|
|
if (newlen >= dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
dblk->data = newdata;
|
|
dblk->maxsize = newsize;
|
|
}
|
|
numw = fread(dblk->data + dsi, 1, num, fp);
|
|
if (numw < num)
|
|
return E_COPYF4;
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = len - ssi;
|
|
if (num <= 0) /* Nothing to be copied */
|
|
return 0;
|
|
if (ssi + num > len)
|
|
return E_COPY5; /* Insufficient memory in str */
|
|
fiop = findid(id, TRUE);
|
|
if (fiop == NULL)
|
|
return E_COPYF1;
|
|
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_COPYF2;
|
|
}
|
|
numw = fwrite(str->s_str + ssi, 1, num, fp);
|
|
if (numw < num)
|
|
return E_COPYF3;
|
|
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_COPY2;
|
|
if (num < 0)
|
|
num = sblk->datalen - ssi;
|
|
if (num == 0) /* Nothing to be copied */
|
|
return 0;
|
|
if (ssi + num > sblk->datalen)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = dblk->datalen;
|
|
newlen = dsi + num;
|
|
if (newlen <= 0)
|
|
return E_COPY7;
|
|
if (newlen >= dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
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_COPY7;
|
|
if (newlen >= dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
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_COPY2;
|
|
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_COPY7;
|
|
if (newlen >= (size_t)dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
dblk->data = newdata;
|
|
dblk->maxsize = newsize;
|
|
}
|
|
memmove(dblk->data + dsi, str + ssi, num);
|
|
if (newlen > (size_t)dblk->datalen)
|
|
dblk->datalen = newlen;
|
|
return 0;
|
|
}
|
|
#if !defined(HAVE_MEMMOVE)
|
|
/*
|
|
* memmove - simulate the memory move function that deals with overlap
|
|
*
|
|
* Copying between objects that overlap will take place correctly.
|
|
*
|
|
* given:
|
|
* s1 destination
|
|
* s2 source
|
|
* n octet count
|
|
*
|
|
* returns:
|
|
* s1
|
|
*/
|
|
void *
|
|
memmove(void *s1, CONST void *s2, MEMMOVE_SIZE_T n)
|
|
{
|
|
/*
|
|
* firewall
|
|
*/
|
|
if (s1 == NULL || s2 == NULL) {
|
|
math_error("bogus memmove NULL ptr");
|
|
/*NOTREACHED*/
|
|
}
|
|
if (n <= 0) {
|
|
/* neg or 0 count does nothing */
|
|
return s1;
|
|
}
|
|
if ((char *)s1 == (char *)s2) {
|
|
/* copy to same location does nothing */
|
|
return s1;
|
|
}
|
|
|
|
/*
|
|
* determine if we need to deal with overlap copy
|
|
*/
|
|
if ((char *)s1 > (char *)s2 && (char *)s1 < (char *)s2+n) {
|
|
|
|
/*
|
|
* we have to copy backwards ... slowly
|
|
*/
|
|
while (n-- > 0) {
|
|
((char *)s1)[n] = ((char *)s2)[n];
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
* safe ... no overlap problems
|
|
*/
|
|
(void) memcpy(s1, s2, n);
|
|
|
|
}
|
|
return s1;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* 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_COPY2;
|
|
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_COPY5;
|
|
if (dsi < 0)
|
|
dsi = dblk->datalen;
|
|
newlen = dsi + (num*sizeof(HALF));
|
|
if (newlen <= 0)
|
|
return E_COPY7;
|
|
if (newlen >= (size_t)dblk->maxsize) {
|
|
if (noreloc)
|
|
return E_COPY17;
|
|
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");
|
|
/*NOTREACHED*/
|
|
}
|
|
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 ounded up to HALFs */
|
|
HALF *h; /* copy byteswap pointer */
|
|
unsigned long i;
|
|
#endif
|
|
|
|
if (ssi > sblk->datalen)
|
|
return E_COPY2;
|
|
if (num < 0)
|
|
num = sblk->datalen - ssi;
|
|
if (num == 0) /* Nothing to be copied */
|
|
return 0;
|
|
if (ssi + num > sblk->datalen)
|
|
return E_COPY5;
|
|
if (dsi < 0)
|
|
dsi = dnum->num.len;
|
|
newlen = dsi + ((num+sizeof(HALF)-1)/sizeof(HALF));
|
|
if (newlen <= 0)
|
|
return E_COPY7;
|
|
|
|
/* 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");
|
|
/*NOTREACHED*/
|
|
}
|
|
/* 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;
|
|
}
|