modified: src1/input.c
[GalaxyCodeBases.git] / c_cpp / etc / calc / blkcpy.c
blob7e8602005ca58e018329afe18073fb670abf994e
1 /*
2 * blkcpy - general values and related routines used by the calculator
4 * Copyright (C) 1999-2007 Landon Curt Noll and Ernest Bowen
6 * Primary author: Landon Curt Noll
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
15 * Public License for more details.
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL. You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * @(#) $Revision: 30.2 $
23 * @(#) $Id: blkcpy.c,v 30.2 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/blkcpy.c,v $
26 * Under source code control: 1997/04/18 20:41:26
27 * File existed as early as: 1997
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
33 #include <stdio.h>
34 #include <sys/types.h>
35 #include "calc.h"
36 #include "value.h"
37 #include "file.h"
38 #include "blkcpy.h"
39 #include "str.h"
43 * copystod - copy num indexed items from source value to destination value
45 * given:
46 * ssi = source starting index
47 * num = number of items (octets or values) to be copied
48 * sdi = destination starting index
50 * returns:
51 * zero if successful, otherwise error-code number
53 int
54 copystod(VALUE *svp, long ssi, long num, VALUE *dvp, long dsi)
56 BLOCK *sblk;
57 BLOCK *dblk;
58 BOOL noreloc;
60 sblk = NULL;
61 dblk = NULL;
64 * check protections
66 if (svp->v_subtype & V_NOCOPYFROM)
67 return E_COPY13;
68 if (dvp->v_subtype & V_NOCOPYTO)
69 return E_COPY14;
70 noreloc = ((dvp->v_subtype & V_NOREALLOC) != 0);
73 * determine/check source type
75 switch(svp->v_type) {
76 case V_NBLOCK:
77 if (svp->v_nblock->subtype & V_NOCOPYFROM)
78 return E_COPY15;
79 sblk = svp->v_nblock->blk;
80 if (sblk->data == NULL)
81 return E_COPY8;
82 break;
83 case V_BLOCK:
84 sblk = svp->v_block;
85 break;
86 case V_STR:
87 case V_OCTET:
88 case V_NUM:
89 case V_FILE:
90 case V_MAT:
91 case V_LIST:
92 break;
93 default:
94 return E_COPY9;
98 * determine/check destination type
100 switch(dvp->v_type) {
101 case V_NBLOCK:
102 if (dvp->v_nblock->subtype & V_NOCOPYTO)
103 return E_COPY16;
104 noreloc |=((dvp->v_nblock->subtype & V_NOREALLOC) != 0);
105 dblk = dvp->v_nblock->blk;
106 if (dblk->data == NULL)
107 return E_COPY10;
108 break;
109 case V_BLOCK:
110 noreloc = ((dvp->v_subtype & V_NOREALLOC) != 0);
111 dblk = dvp->v_block;
112 break;
113 case V_STR:
114 case V_NUM:
115 case V_FILE:
116 case V_MAT:
117 case V_LIST:
118 break;
119 default:
120 return E_COPY11;
124 * copy based on source
126 switch (svp->v_type) {
127 case V_BLOCK:
128 case V_NBLOCK:
130 * copy from a block
132 switch(dvp->v_type) {
133 case V_BLOCK:
134 case V_NBLOCK:
135 return copyblk2blk(sblk, ssi, num, dblk, dsi, noreloc);
136 case V_NUM:
138 NUMBER *n; /* modified number */
139 int rt; /* return code */
141 /* copy to a number */
142 rt = copyblk2num(sblk, ssi, num, dvp->v_num, dsi, &n);
143 if (rt == 0) {
144 qfree(dvp->v_num);
145 dvp->v_num = n;
147 return rt;
149 case V_FILE:
150 return copyblk2file(sblk, ssi, num, dvp->v_file, dsi);
151 case V_MAT:
152 return copyblk2mat(sblk, ssi, num, dvp->v_mat, dsi);
153 case V_STR:
154 return copyblk2str(sblk, ssi, num, dvp->v_str, dsi);
156 return E_COPY12;
158 case V_STR:
159 switch(dvp->v_type) {
160 case V_BLOCK:
161 case V_NBLOCK:
162 /* copy to a block */
163 return copystr2blk(svp->v_str, ssi, num, dblk, dsi,
164 noreloc);
165 case V_FILE:
166 return copystr2file(svp->v_str, ssi, num,
167 dvp->v_file, dsi);
168 case V_STR:
169 return copystr2str(svp->v_str, ssi, num, dvp->v_str,
170 dsi);
172 return E_COPY12;
174 case V_OCTET:
175 switch(dvp->v_type) {
176 case V_BLOCK:
177 case V_NBLOCK:
178 return copyostr2blk((char *) svp->v_octet, ssi, num,
179 dblk, dsi, noreloc);
180 case V_STR:
181 return copyostr2str((char *) svp->v_octet, ssi, num,
182 dvp->v_str, dsi);
184 return E_COPY12;
186 case V_NUM:
189 * copy from a number
191 if (dblk != NULL) {
192 /* copy to a block */
193 return copynum2blk(svp->v_num, ssi, num, dblk,
194 dsi, noreloc);
196 switch (dvp->v_type) {
197 case V_MAT:
198 /* copy to a matrix */
199 return E_COPY12; /* not yet - XXX */
200 case V_LIST:
201 /* copy to a list */
202 return E_COPY12; /* not yet - XXX */
204 break;
205 case V_FILE:
208 * copy from a file
210 if (dblk != NULL) {
211 /* copy to a block */
212 return copyfile2blk(svp->v_file, ssi, num,
213 dblk, dsi, noreloc);
215 switch (dvp->v_type) {
216 case V_NUM:
217 /* copy to a number */
218 return E_COPY12; /* not yet - XXX */
220 break;
222 case V_MAT:
225 * copy from a matrix
227 if (dblk != NULL) {
228 /* copy to a block */
229 return copymat2blk(svp->v_mat, ssi, num, dblk,
230 dsi, noreloc);
232 switch (dvp->v_type) {
233 case V_MAT:
234 /* copy to a matrix */
235 return copymat2mat(svp->v_mat, ssi, num,
236 dvp->v_mat, dsi);
237 case V_LIST:
238 /* copy to a list */
239 return copymat2list(svp->v_mat, ssi, num,
240 dvp->v_list, dsi);
242 break;
244 case V_LIST:
247 * copy from a list
249 if (dblk != NULL) {
250 /* copy to a block */
251 return E_COPY12; /* not yet - XXX */
253 switch (dvp->v_type) {
254 case V_MAT:
255 /* copy to a matrix */
256 return copylist2mat(svp->v_list, ssi, num,
257 dvp->v_mat, dsi);
258 case V_LIST:
259 /* copy to a list */
260 return copylist2list(svp->v_list, ssi, num,
261 dvp->v_list, dsi);
263 break;
267 * unsupported copy combination
269 return E_COPY12;
274 * copymat2mat - copy matrix to matrix
277 copymat2mat(MATRIX *smat, long ssi, long num, MATRIX *dmat, long dsi)
279 long i;
280 VALUE *vp;
281 VALUE *vq;
282 VALUE *vtemp;
283 unsigned short subtype;
285 if (ssi > smat->m_size)
286 return E_COPY2;
288 if (num < 0)
289 num = smat->m_size - ssi;
290 if (ssi + num > smat->m_size)
291 return E_COPY5;
292 if (num == 0)
293 return 0;
294 if (dsi < 0)
295 dsi = 0;
296 if (dsi + num > dmat->m_size)
297 return E_COPY7;
298 vtemp = (VALUE *) malloc(num * sizeof(VALUE));
299 if (vtemp == NULL) {
300 math_error("Out of memory for mat-to-mat copy");
301 /*NOTREACHED*/
303 vp = smat->m_table + ssi;
304 vq = vtemp;
305 i = num;
306 while (i-- > 0)
307 copyvalue(vp++, vq++);
308 vp = vtemp;
309 vq = dmat->m_table + dsi;
310 for (i = num; i > 0; i--, vp++, vq++) {
311 subtype = vq->v_subtype;
312 freevalue(vq);
313 *vq = *vp;
314 vq->v_subtype |= subtype;
316 free(vtemp);
317 return 0;
322 * copyblk2mat - copy block to matrix
325 copyblk2mat(BLOCK *blk, long ssi, long num, MATRIX *dmat, long dsi)
327 OCTET *op;
328 VALUE *vp;
329 VALUE *vq;
330 VALUE *vtemp;
331 long i;
332 unsigned short subtype;
334 if (ssi > blk->datalen)
335 return E_COPY2;
336 if (num < 0)
337 num = blk->datalen - ssi;
338 if (ssi + num > blk->datalen)
339 return E_COPY5;
340 if (num == 0)
341 return 0;
342 if (dsi < 0)
343 dsi = 0;
344 if (dsi + num > dmat->m_size)
345 return E_COPY7;
346 op = blk->data + ssi;
347 vtemp = (VALUE *) malloc(num * sizeof(VALUE));
348 if (vtemp == NULL) {
349 math_error("Out of memory for block-to-matrix copy");
350 /*NOTREACHED*/
352 vp = vtemp;
353 i = num;
354 while (i-- > 0) {
355 vp->v_type = V_NUM;
356 vp->v_subtype = V_NOSUBTYPE;
357 vp->v_num = itoq((long) *op++);
358 vp++;
360 vp = vtemp;
361 vq = dmat->m_table + dsi;
362 for (i = num; i > 0; i--, vp++, vq++) {
363 subtype = vq->v_subtype;
364 freevalue(vq);
365 *vq = *vp;
366 vq->v_subtype |= subtype;
368 free(vtemp);
369 return 0;
374 * copymat2blk - copy matrix to block
377 copymat2blk(MATRIX *smat, long ssi, long num, BLOCK *dblk, long dsi,
378 BOOL noreloc)
380 long i;
381 long newlen;
382 long newsize;
383 USB8 *newdata;
384 VALUE *vp;
385 OCTET *op;
387 if (ssi > smat->m_size)
388 return E_COPY2;
389 if (num < 0)
390 num = smat->m_size - ssi;
391 if (num == 0)
392 return 0;
393 if (ssi + num > smat->m_size)
394 return E_COPY5;
395 if (dsi < 0)
396 dsi = dblk->datalen;
397 newlen = dsi + num;
398 if (newlen <= 0)
399 return E_COPY7;
400 if (newlen >= dblk->maxsize) {
401 if (noreloc)
402 return E_COPY17;
403 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
404 newdata = (USB8*) realloc(dblk->data, newsize);
405 if (newdata == NULL) {
406 math_error("Out of memory for matrix-to-block copy");
407 /*NOTREACHED*/
409 dblk->data = newdata;
410 dblk->maxsize = newsize;
412 vp = smat->m_table + ssi;
413 op = dblk->data + dsi;
414 for (i = num; i > 0; i--)
415 copy2octet(vp++, op++);
416 if (newlen > dblk->datalen)
417 dblk->datalen = newlen;
418 return 0;
423 * copymat2list - copy matrix to list
426 copymat2list(MATRIX *smat, long ssi, long num, LIST *lp, long dsi)
428 VALUE *vp;
429 VALUE *vq;
430 LISTELEM *ep;
431 VALUE *vtemp;
432 long i;
433 unsigned short subtype;
435 if (ssi > smat->m_size)
436 return E_COPY2;
437 if (num < 0)
438 num = smat->m_size - ssi;
439 if (num == 0)
440 return 0;
441 if (ssi + num > smat->m_size)
442 return E_COPY5;
443 if (dsi < 0)
444 dsi = 0;
445 if (dsi + num > lp->l_count)
446 return E_COPY7;
447 vtemp = (VALUE *) malloc(num * sizeof(VALUE));
448 if (vtemp == NULL) {
449 math_error("Out of memory for matrix-to-list copy");
450 /*NOTREACHED*/
452 vp = smat->m_table + ssi;
453 vq = vtemp;
454 i = num;
455 while (i-- > 0)
456 copyvalue(vp++, vq++);
457 vq = vtemp;
458 ep = listelement(lp, (long) dsi);
459 i = num;
460 while (i-- > 0) {
461 subtype = ep->e_value.v_subtype;
462 freevalue(&ep->e_value);
463 ep->e_value = *vq++;
464 ep->e_value.v_subtype |= subtype;
465 ep = ep->e_next;
467 free(vtemp);
468 return 0;
473 * copymat2list - copy list to matrix
476 copylist2mat(LIST *lp, long ssi, long num, MATRIX *dmat, long dsi)
478 VALUE *vp;
479 VALUE *vq;
480 LISTELEM *ep;
481 VALUE *vtemp;
482 long i;
483 unsigned short subtype;
485 if (ssi > lp->l_count)
486 return E_COPY2;
487 if (num < 0)
488 num = lp->l_count - ssi;
489 if (num == 0)
490 return 0;
491 if (ssi + num > lp->l_count)
492 return E_COPY5;
493 if (dsi < 0)
494 dsi = 0;
495 if (dsi + num > dmat->m_size)
496 return E_COPY7;
497 vtemp = (VALUE *) malloc(num * sizeof(VALUE));
498 if (vtemp == NULL) {
499 math_error("Out of memory for list-to-matrix copy");
500 /*NOTREACHED*/
502 ep = listelement(lp, (long) ssi);
503 vp = vtemp;
504 i = num;
505 while (i-- > 0) {
506 copyvalue(&ep->e_value, vp++);
507 ep = ep->e_next;
509 vp = vtemp;
510 vq = dmat->m_table + dsi;
511 for (i = num; i > 0; i--, vp++, vq++) {
512 subtype = vq->v_subtype;
513 freevalue(vq);
514 *vq = *vp;
515 vq->v_subtype |= subtype;
517 free(vtemp);
518 return 0;
523 * copylist2list - copy list to list
526 copylist2list(LIST *slp, long ssi, long num, LIST *dlp, long dsi)
528 long i;
529 LISTELEM *sep;
530 LISTELEM *dep;
531 VALUE *vtemp;
532 VALUE *vp;
533 unsigned short subtype;
535 if (ssi > slp->l_count)
536 return E_COPY2;
537 if (num < 0)
538 num = slp->l_count - ssi;
539 if (num == 0)
540 return 0;
541 if (ssi + num > slp->l_count)
542 return E_COPY5;
543 if (dsi < 0)
544 dsi = 0;
545 if (dsi + num > dlp->l_count)
546 return E_COPY7;
547 vtemp = (VALUE *) malloc(num * sizeof(VALUE));
548 if (vtemp == NULL) {
549 math_error("Out of memory for list-to-list copy");
550 /*NOTREACHED*/
552 sep = listelement(slp, (long) ssi);
553 vp = vtemp;
554 i = num;
555 while (i-- > 0) {
556 copyvalue(&sep->e_value, vp++);
557 sep = sep->e_next;
559 dep = listelement(dlp, (long) dsi);
560 vp = vtemp;
561 i = num;
562 while (i-- > 0) {
563 subtype = dep->e_value.v_subtype;
564 freevalue(&dep->e_value);
565 dep->e_value = *vp++;
566 dep->e_value.v_subtype |= subtype;
567 dep = dep->e_next;
569 free(vtemp);
570 return 0;
575 * copyblk2file - copy block to file
578 copyblk2file(BLOCK *sblk, long ssi, long num, FILEID id, long dsi)
580 FILEIO *fiop;
581 FILE *fp;
582 long numw;
584 if (ssi > sblk->datalen)
585 return E_COPY2;
586 if (num < 0)
587 num = sblk->datalen - ssi;
588 if (num == 0)
589 return 0;
591 fiop = findid(id, TRUE);
592 if (fiop == NULL)
593 return E_COPYF1;
594 fp = fiop->fp;
595 if (id == 1 || id == 2) {
596 numw = idfputstr(id, (char *)sblk->data + ssi); /* XXX */
597 return 0;
599 if (dsi >= 0) {
600 if (fseek(fp, dsi, 0))
601 return E_COPYF2;
603 numw = fwrite(sblk->data + ssi, 1, num, fp);
604 if (numw < num)
605 return E_COPYF3;
606 fflush(fp);
607 return 0;
612 * copyfile2blk - copy file to block
615 copyfile2blk(FILEID id, long ssi, long num, BLOCK *dblk, long dsi, BOOL noreloc)
617 FILEIO *fiop;
618 FILE *fp;
619 long numw;
620 ZVALUE fsize;
621 long filelen;
622 long newlen;
623 long newsize;
624 OCTET *newdata;
626 if (id < 3) /* excludes copying from stdin */
627 return E_COPYF1;
628 fiop = findid(id, FALSE);
629 if (fiop == NULL)
630 return E_COPYF1;
632 fp = fiop->fp;
634 if (get_open_siz(fp, &fsize))
635 return E_COPYF2;
636 if (zge31b(fsize)) {
637 zfree(fsize);
638 return E_COPY5;
640 filelen = ztoi(fsize);
641 zfree(fsize);
643 if (ssi > filelen)
644 return E_COPY2;
645 if (num < 0)
646 num = filelen - ssi;
647 if (num == 0)
648 return 0;
649 if (ssi + num > filelen)
650 return E_COPY5;
651 if (fseek(fp, ssi, 0)) /* using system fseek XXX */
652 return E_COPYF2;
653 if (dsi < 0)
654 dsi = dblk->datalen;
655 newlen = dsi + num;
656 if (newlen <= 0)
657 return E_COPY7;
658 if (newlen >= dblk->maxsize) {
659 if (noreloc)
660 return E_COPY17;
661 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
662 newdata = (USB8*) realloc(dblk->data, newsize);
663 if (newdata == NULL) {
664 math_error("Out of memory for block-to-block copy");
665 /*NOTREACHED*/
667 dblk->data = newdata;
668 dblk->maxsize = newsize;
670 numw = fread(dblk->data + dsi, 1, num, fp);
671 if (numw < num)
672 return E_COPYF4;
673 if (newlen > dblk->datalen)
674 dblk->datalen = newlen;
675 return 0;
680 * copystr2file - copy string to file
683 copystr2file(STRING *str, long ssi, long num, FILEID id, long dsi)
685 long len;
686 FILEIO *fiop;
687 long numw;
688 FILE *fp;
690 len = str->s_len;
692 if (ssi >= len)
693 return E_COPY2;
694 if (num < 0)
695 num = len - ssi;
696 if (num <= 0) /* Nothing to be copied */
697 return 0;
698 if (ssi + num > len)
699 return E_COPY5; /* Insufficient memory in str */
700 fiop = findid(id, TRUE);
701 if (fiop == NULL)
702 return E_COPYF1;
703 fp = fiop->fp;
704 if (id == 1 || id == 2) {
705 numw = idfputstr(id, str->s_str + ssi); /* XXX */
706 return 0;
708 if (dsi >= 0) {
709 if (fseek(fp, dsi, 0))
710 return E_COPYF2;
712 numw = fwrite(str->s_str + ssi, 1, num, fp);
713 if (numw < num)
714 return E_COPYF3;
715 fflush(fp);
716 return 0;
721 * copyblk2blk - copy block to block
724 copyblk2blk(BLOCK *sblk, long ssi, long num, BLOCK *dblk, long dsi,
725 BOOL noreloc)
727 long newlen;
728 long newsize;
729 USB8 *newdata;
731 if (ssi > sblk->datalen)
732 return E_COPY2;
733 if (num < 0)
734 num = sblk->datalen - ssi;
735 if (num == 0) /* Nothing to be copied */
736 return 0;
737 if (ssi + num > sblk->datalen)
738 return E_COPY5;
739 if (dsi < 0)
740 dsi = dblk->datalen;
741 newlen = dsi + num;
742 if (newlen <= 0)
743 return E_COPY7;
744 if (newlen >= dblk->maxsize) {
745 if (noreloc)
746 return E_COPY17;
747 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
748 newdata = (USB8*) realloc(dblk->data, newsize);
749 if (newdata == NULL) {
750 math_error("Out of memory for block-to-block copy");
751 /*NOTREACHED*/
753 dblk->data = newdata;
754 dblk->maxsize = newsize;
756 memmove(dblk->data + dsi, sblk->data + ssi, num);
757 if (newlen > dblk->datalen)
758 dblk->datalen = newlen;
759 return 0;
764 * copystr2blk - copy string to block
767 copystr2blk(STRING *str, long ssi, long num, BLOCK *dblk, long dsi,
768 BOOL noreloc)
770 long len;
771 long newlen;
772 long newsize;
773 USB8 *newdata;
775 len = str->s_len;
777 if (ssi >= len)
778 return E_COPY2;
779 if (num < 0)
780 num = len - ssi;
781 if (num <= 0) /* Nothing to be copied */
782 return 0;
783 if (dsi < 0)
784 dsi = dblk->datalen;
785 newlen = dsi + num + 1;
786 if (newlen <= 0)
787 return E_COPY7;
788 if (newlen >= dblk->maxsize) {
789 if (noreloc)
790 return E_COPY17;
791 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
792 newdata = (USB8*) realloc(dblk->data, newsize);
793 if (newdata == NULL) {
794 math_error("Out of memory for string-to-block copy");
795 /*NOTREACHED*/
797 dblk->data = newdata;
798 dblk->maxsize = newsize;
800 memmove(dblk->data + dsi, str->s_str + ssi, num);
801 dblk->data[dsi + num] = '\0';
802 if (newlen > dblk->datalen)
803 dblk->datalen = newlen;
804 return 0;
809 * copystr2str - copy up to num characters from sstr (starting at
810 * index ssi) to dstr (starting at index dsi); num is reduced if there
811 * are insufficient characters in sstr or insufficient space in dstr.
814 copystr2str(STRING *sstr, long ssi, long num, STRING *dstr, long dsi)
816 char *c, *c1;
818 if (num < 0 || (size_t)(ssi + num) > sstr->s_len)
819 num = sstr->s_len - ssi;
820 if (num <= 0)
821 return 0; /* Nothing to be copied */
822 if (dsi < 0) /* default destination index */
823 dsi = 0;
824 if ((size_t)(dsi + num) > dstr->s_len)
825 num = dstr->s_len - dsi;
826 c1 = sstr->s_str + ssi;
827 c = dstr->s_str + dsi;
828 while (num-- > 0)
829 *c++ = *c1++;
830 return 0;
835 * copyblk2str - copy up to num characters from sblk (starting at
836 * index ssi) to str (starting at index dsi); num is reduced if there
837 * is insufficient data in blk or insufficient space in str
840 copyblk2str(BLOCK *sblk, long ssi, long num, STRING *dstr, long dsi)
842 USB8 *c, *c1;
844 if (num < 0 || ssi + num > sblk->datalen)
845 num = sblk->datalen - ssi;
846 if (num <= 0)
847 return 0; /* Nothing to be copied */
848 if (dsi < 0) /* default destination index */
849 dsi = 0;
850 if ((size_t)(dsi + num) > dstr->s_len)
851 num = dstr->s_len - dsi;
852 c1 = sblk->data + ssi;
853 c = (USB8 *)dstr->s_str + dsi;
854 while (num-- > 0)
855 *c++ = *c1++;
856 return 0;
859 * copyostr2str - copy octet-specified string to string
862 copyostr2str(char *sstr, long ssi, long num, STRING *dstr, long dsi)
864 size_t len;
865 char *c, *c1;
867 len = strlen(sstr);
869 if (num < 0 || (size_t)(ssi + num) > len)
870 num = len - ssi;
871 if (num <= 0) /* Nothing to be copied */
872 return 0;
873 if (dsi < 0)
874 dsi = 0; /* Default destination index */
875 if ((size_t)(dsi + num) > dstr->s_len)
876 num = dstr->s_len - dsi;
877 c1 = sstr + ssi;
878 c = dstr->s_str + dsi;
879 while (num-- > 0)
880 *c++ = *c1++;
881 return 0;
886 * copyostr2blk - copy octet-specified string to block
889 copyostr2blk(char *str,long ssi,long num,BLOCK *dblk,long dsi,BOOL noreloc)
891 size_t len;
892 size_t newlen;
893 size_t newsize;
894 USB8 *newdata;
896 len = strlen(str) + 1;
898 if (ssi > 0 && (size_t)ssi > len)
899 return E_COPY2;
900 if (num < 0 || (size_t)(ssi + num) > len)
901 num = len - ssi;
902 if (num <= 0) /* Nothing to be copied */
903 return 0;
904 if (dsi < 0)
905 dsi = dblk->datalen; /* Default destination index */
906 newlen = dsi + num;
907 if (newlen <= 0)
908 return E_COPY7;
909 if (newlen >= (size_t)dblk->maxsize) {
910 if (noreloc)
911 return E_COPY17;
912 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
913 newdata = (USB8*) realloc(dblk->data, newsize);
914 if (newdata == NULL) {
915 math_error("Out of memory for string-to-block copy");
916 /*NOTREACHED*/
918 dblk->data = newdata;
919 dblk->maxsize = newsize;
921 memmove(dblk->data + dsi, str + ssi, num);
922 if (newlen > (size_t)dblk->datalen)
923 dblk->datalen = newlen;
924 return 0;
926 #if !defined(HAVE_MEMMOVE)
928 * memmove - simulate the memory move function that deals with overlap
930 * Copying between objects that overlap will take place correctly.
932 * given:
933 * s1 destination
934 * s2 source
935 * n octet count
937 * returns:
938 * s1
940 void *
941 memmove(void *s1, CONST void *s2, MEMMOVE_SIZE_T n)
944 * firewall
946 if (s1 == NULL || s2 == NULL) {
947 math_error("bogus memmove NULL ptr");
948 /*NOTREACHED*/
950 if (n <= 0) {
951 /* neg or 0 count does nothing */
952 return s1;
954 if ((char *)s1 == (char *)s2) {
955 /* copy to same location does nothing */
956 return s1;
960 * determine if we need to deal with overlap copy
962 if ((char *)s1 > (char *)s2 && (char *)s1 < (char *)s2+n) {
965 * we have to copy backwards ... slowly
967 while (n-- > 0) {
968 ((char *)s1)[n] = ((char *)s2)[n];
971 } else {
974 * safe ... no overlap problems
976 (void) memcpy(s1, s2, n);
979 return s1;
981 #endif
985 * copynum2blk - copy number numerator to block
988 copynum2blk(NUMBER *snum, long ssi, long num, BLOCK *dblk, long dsi,
989 BOOL noreloc)
991 size_t newlen;
992 size_t newsize;
993 USB8 *newdata;
994 #if CALC_BYTE_ORDER == BIG_ENDIAN
995 ZVALUE *swnum; /* byte swapped numerator */
996 #endif
998 if (ssi > snum->num.len)
999 return E_COPY2;
1000 if (num < 0)
1001 num = snum->num.len - ssi;
1002 if (num == 0) /* Nothing to be copied */
1003 return 0;
1004 if (ssi + num > snum->num.len)
1005 return E_COPY5;
1006 if (dsi < 0)
1007 dsi = dblk->datalen;
1008 newlen = dsi + (num*sizeof(HALF));
1009 if (newlen <= 0)
1010 return E_COPY7;
1011 if (newlen >= (size_t)dblk->maxsize) {
1012 if (noreloc)
1013 return E_COPY17;
1014 newsize = (1 + newlen/dblk->blkchunk) * dblk->blkchunk;
1015 newdata = (USB8*) realloc(dblk->data, newsize);
1016 if (newdata == NULL) {
1017 math_error("Out of memory for num-to-block copy");
1018 /*NOTREACHED*/
1020 dblk->data = newdata;
1021 dblk->maxsize = newsize;
1023 #if CALC_BYTE_ORDER == LITTLE_ENDIAN
1024 memmove(dblk->data+dsi, (char *)(snum->num.v+ssi), num*sizeof(HALF));
1025 #else
1026 swnum = swap_b8_in_ZVALUE(NULL, &(snum->num), FALSE);
1027 memmove(dblk->data+dsi, (char *)(swnum->v+ssi), num*sizeof(HALF));
1028 zfree(*swnum);
1029 #endif
1030 if (newlen > (size_t)dblk->datalen)
1031 dblk->datalen = newlen;
1032 return 0;
1037 * copyblk2num - copy block to number
1040 copyblk2num(BLOCK *sblk, long ssi, long num, NUMBER *dnum, long dsi,
1041 NUMBER **res)
1043 size_t newlen;
1044 NUMBER *ret; /* cloned and modified numerator */
1045 #if CALC_BYTE_ORDER == BIG_ENDIAN
1046 HALF *swapped; /* byte swapped input data */
1047 unsigned long halflen; /* length of the input ounded up to HALFs */
1048 HALF *h; /* copy byteswap pointer */
1049 unsigned long i;
1050 #endif
1052 if (ssi > sblk->datalen)
1053 return E_COPY2;
1054 if (num < 0)
1055 num = sblk->datalen - ssi;
1056 if (num == 0) /* Nothing to be copied */
1057 return 0;
1058 if (ssi + num > sblk->datalen)
1059 return E_COPY5;
1060 if (dsi < 0)
1061 dsi = dnum->num.len;
1062 newlen = dsi + ((num+sizeof(HALF)-1)/sizeof(HALF));
1063 if (newlen <= 0)
1064 return E_COPY7;
1066 /* quasi-clone the numerator to the new size */
1067 ret = qalloc();
1068 ret->num.sign = dnum->num.sign;
1069 ret->num.v = alloc(newlen);
1070 ret->num.len = newlen;
1071 /* ensure that any trailing octets will be zero filled */
1072 ret->num.v[newlen-1] = 0;
1073 zcopyval(dnum->num, ret->num);
1074 if (!zisunit(ret->den)) {
1075 ret->den.len = dnum->den.len;
1076 ret->den.v = alloc(dnum->den.len);
1077 zcopyval(dnum->den, ret->den);
1080 /* move the data */
1081 #if CALC_BYTE_ORDER == LITTLE_ENDIAN
1082 memmove((char *)(ret->num.v + dsi), sblk->data + ssi, num);
1083 #else
1084 /* form a HALF aligned copy of the input */
1085 halflen = (num+sizeof(HALF)-1) / sizeof(HALF);
1086 swapped = (HALF *)malloc(halflen * sizeof(HALF));
1087 if (swapped == NULL) {
1088 math_error("Out of memory for block-to-num copy");
1089 /*NOTREACHED*/
1091 /* ensure that any trailing octets will be zero filled */
1092 swapped[halflen-1] = 0;
1093 memcpy(swapped, sblk->data + ssi, num);
1094 /* byte swap the copy of the input */
1095 for (i=0, h=swapped; i < halflen; ++i, ++h) {
1096 SWAP_B8_IN_HALF(h, h);
1098 /* copy over whole byte-swapped HALFs */
1099 memcpy((char *)(ret->num.v + dsi), swapped,
1100 (num/sizeof(HALF))*sizeof(HALF));
1101 /* copy over any octets in the last partial HALF */
1102 i = num % sizeof(HALF);
1103 if (i != 0) {
1104 memcpy((char *)(ret->num.v + dsi)+num-i,
1105 (char *)swapped + num-i, i);
1107 free(swapped);
1108 #endif
1109 /* save new number */
1110 *res = ret;
1111 return 0;