]> git.saurik.com Git - apple/security.git/blame - SecuritySNACCRuntime/c-lib/src/exp-buf.c
Security-54.1.9.tar.gz
[apple/security.git] / SecuritySNACCRuntime / c-lib / src / exp-buf.c
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19#if defined (USE_EXP_BUF) || defined (USE_GEN_BUF)
20/*
21 * .../c-lib/src/exp-buf.c - buffer routines for the buffer structure
22 *
23 *
24 * --------- ----------
25 * | ExpBuf |<------>| ExpBuf |<------> ...ExpBufs
26 * | |--- | |---
27 * ---------- | ---------- |
28 * V V
29 * -------- --------
30 * | DATA | | DATA |
31 * | BLK | | BLK |
32 * -------- --------
33 *
34 *
35 * ExpBuf
36 * --------------
37 * | readError |
38 * | writeError |
39 * | dataStart |-----------
40 * | dataEnd |-------- |
41 * | curr |------ | |
42 * | next | | | |
43 * | prev | | | | data
44 * | blkStart |=====|=|==|==>--------------------------
45 * | blkEnd |--- | | | | | (each line
46 * -------------- | | | | | | reps a byte
47 * | | | |-->| - - - - - - - - - - - -| diff in addr)
48 * | | | | valid |
49 * | |-|----->| |
50 * | | | data |
51 * | | | |
52 * | | | - - - - - - - - - - - -|
53 * | |----->|(one byte after last valid data byte)
54 * | | |
55 * | --------------------------
56 * |-----------> (one byte after last byte in data blk)
57 *
58 *
59 * readError - set to non-zero to indicate attempt to read past end of
60 * of data
61 * writeError- set to non-zero to indicate write error.
62 * Set if Alloc of new buf fails
63 * dataStart - pts to first VALID data byte ie *dataStart is first byte
64 * dataEnd - pts to byte AFTER last VALID byte *dataEnd is not in the data
65 * but *(dataEnd -1) is in the data
66 * curr - used for current read ptr - points to next byte to be read
67 * so *curr is the next byte to be read.
68 * next - pts to next BUF in list, NULL for last BUF in list
69 * prev - pts to prev BUF in list, NULL for first BUF in list
70 * blkStart - pts to start of the data blk. *blkStart is first byte
71 * in the buffer's data blk.
72 * blkEnd - pts to byte AFTER last writable byte of the dataBlk.
73 * *(blkEnd-1) is the last byte in the buffer's data blk.
74 *
75 * NOTES:
76 * - dataEnd is currently always the same as blkEnd
77 * - at End Of Data (EOD) (no more data to be read)
78 * if (curr == dataEnd)
79 * - buffer has no valid data if (dataStart == dataEnd)
80 * - number of valid data bytes = (dataEnd - dataStart)
81 * - size of the data block = (blkEnd - blkStart)
82 *
83 * - the write reverse routines modify dataStart
84 * - the read routines modify the curr ptr.
85 * - there are no 'forward' write routines at the moment
86 * (if there were they would adjust dataEnd)
87 *
88 *
89 * Copyright (C) 1992 Michael Sample and the University of British Columbia
90 *
91 * This library is free software; you can redistribute it and/or
92 * modify it provided that this copyright/license information is retained
93 * in original form.
94 *
95 * If you modify this file, you must clearly indicate your changes.
96 *
97 * This source code is distributed in the hope that it will be
98 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
99 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
100 *
a66d0d4a 101 * $Header: /cvs/root/Security/SecuritySNACCRuntime/c-lib/src/Attic/exp-buf.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $
bac41a7b
A
102 * $Log: exp-buf.c,v $
103 * Revision 1.1.1.1 2001/05/18 23:14:08 mb
104 * Move from private repository to open source repository
105 *
106 * Revision 1.2 2001/05/05 00:59:25 rmurphy
107 * Adding darwin license headers
108 *
109 * Revision 1.1.1.1 1999/03/16 18:06:32 aram
110 * Originals from SMIME Free Library.
111 *
112 * Revision 1.2 1995/07/27 09:05:29 rj
113 * merged type table routines and code used by its gen-bufs.
114 *
115 * changed `_' to `-' in file names.
116 *
117 * Revision 1.1 1994/08/28 09:46:05 rj
118 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
119 *
120 */
121
122#include "asn-config.h"
123#include "gen-buf.h"
124#include "exp-buf.h"
125
126
127/* default buffer data block size (used when allocating) */
128unsigned long expBufDataBlkSizeG = 1024;
129
130
131#if defined (DEBUG) || defined (USE_GEN_BUF) /* otherwise macros */
132
133#ifdef USE_GEN_BUF
134
135/*
136 * casts are used to overcome void * - ExpBuf * conflict
137 * be careful if you modify param lists etc.
138 */
139static struct GenBuf expBufOpsG =
140{
141 (BufGetByteFcn) ExpBufGetByte,
142 (BufGetSegFcn) ExpBufGetSeg,
143 (BufCopyFcn) ExpBufCopy,
144 (BufSkipFcn) ExpBufSkip,
145 (BufPeekByteFcn) ExpBufPeekByte,
146 (BufPeekSegFcn) ExpBufPeekSeg,
147 (BufPeekCopyFcn) ExpBufPeekCopy,
148 (BufPutByteRvsFcn) ExpBufPutByteRvs,
149 (BufPutSegRvsFcn) ExpBufPutSegRvs,
150 (BufReadErrorFcn) ExpBufReadError,
151 (BufWriteErrorFcn) ExpBufWriteError,
152 NULL,
153 NULL
154};
155
156#endif
157
158/*
159 * remember: ExpBufs are used via a handle (double ptr)
160 * in the standardized buffer routines. This allows
161 * the 'current' expbuf in the list of expbuf to be the arg.
162 * The list is doubly linked so you can always find
163 * the head or tail given any expbuf in the list
164 */
165void
166PutExpBufInGenBuf PARAMS ((eb, gb),
167 ExpBuf *eb _AND_
168 GenBuf *gb)
169{
170 *gb = expBufOpsG; /* structure assignemnt */
171 gb->bufInfo = &gb->spare; /* handle to expbuf */
172 gb->spare = eb;
173} /* PutExpBufInGenBuf */
174
175/*
176 * sets the size of the data block to attach to
177 * an ExpBuf when allocating a new one
178 */
179void
180ExpBufInit PARAMS ((dataBlkSize),
181 unsigned long dataBlkSize)
182{
183 expBufDataBlkSizeG = dataBlkSize;
184} /* InitBuffers */
185
186/*
187 * Allocates and returns an uninitialized ExpBuf with
188 * no a data attached.
189 */
190ExpBuf*
191ExpBufAllocBuf()
192{
193 return (ExpBuf*)malloc (sizeof (ExpBuf));
194}
195
196void
197ExpBufFreeBuf PARAMS ((ptr),
198 ExpBuf *ptr)
199{
200 free (ptr);
201}
202
203char*
204ExpBufAllocData()
205{
206 return (char*)malloc (expBufDataBlkSizeG);
207}
208
209void
210ExpBufFreeData PARAMS ((ptr),
211 char *ptr)
212{
213 free (ptr);
214}
215
216void
217ExpBufFreeBufAndData PARAMS ((b),
218 ExpBuf *b)
219{
220 ExpBufFreeData ((b)->blkStart);
221 ExpBufFreeBuf (b);
222} /* ExpBufFreeBufAndData */
223
224ExpBuf*
225ExpBufNext PARAMS ((b),
226 ExpBuf *b)
227{
228 return b->next;
229}
230
231ExpBuf*
232ExpBufPrev PARAMS ((b),
233 ExpBuf *b)
234{
235 return b->prev;
236}
237
238int
239ExpBufReadError PARAMS ((b),
240 ExpBuf **b)
241{
242 return (*b)->readError;
243} /* ExpBufReadError */
244
245int
246ExpBufWriteError PARAMS ((b),
247 ExpBuf **b)
248{
249 return (*b)->writeError;
250} /* ExpBufWriteError */
251
252/*
253 * set curr ptr used in reads to the first byte
254 * to be read
255 */
256void
257ExpBufResetInReadMode PARAMS ((b),
258 ExpBuf *b)
259{
260 b->curr = b->dataStart;
261 b->readError = 0;
262 b->writeError = 1; /* catch wrong mode errors */
263}
264
265/*
266 * sets dataStart to end of buffer
267 * so following writes (backward)
268 * over-write any existing data associated with
269 * the buffer
270 */
271void
272ExpBufResetInWriteRvsMode PARAMS ((b),
273 ExpBuf *b)
274{
275 b->dataEnd = b->dataStart = b->blkEnd;
276 b->writeError = 0;
277 b->readError = 1; /* catch wrong mode errors */
278}
279
280
281/*
282 * returns true if no more data can be read from
283 * the given buffer. only valid when buffer in read (fwd)
284 * mode.
285 */
286int
287ExpBufAtEod PARAMS ((b),
288 ExpBuf *b)
289{
290 return b->curr == b->dataEnd;
291}
292
293
294/*
295 * returns true if no more reverse writes can be done
296 * to the buffer. Only valid when buffers in reverse
297 * write mode
298 */
299int
300ExpBufFull PARAMS ((b),
301 ExpBuf *b)
302{
303 return (b)->dataStart == (b)->blkStart;
304}
305
306
307/*
308 * returns true if the given buffer has no
309 * valid data in it's data block
310 */
311int
312ExpBufHasNoData PARAMS ((b),
313 ExpBuf *b)
314{
315 return b->dataStart == b->dataEnd;
316}
317
318
319/*
320 * returns the number of valid data bytes in the
321 * given buffer's data block
322 */
323unsigned long
324ExpBufDataSize PARAMS ((b),
325 ExpBuf *b)
326{
327 return b->dataEnd - b->dataStart;
328}
329
330/*
331 * returns size of data block that is attached to
332 * the given buffer.
333 */
334unsigned long
335ExpBufDataBlkSize PARAMS ((b),
336 ExpBuf *b)
337{
338 return b->blkEnd - b->blkStart;
339}
340
341/*
342 * returns a ptr the beginning of the valid data of
343 * the given buffer.
344 * returns NULL is there is no valid data.
345 */
346char*
347ExpBufDataPtr PARAMS ((b),
348 ExpBuf *b)
349{
350 if (ExpBufHasNoData (b))
351 return NULL;
352 else
353 return b->dataStart;
354}
355
356#endif /* DEBUG || USE_EXP_BUF */
357
358
359/*
360 * returns last ExpBuf in a list of bufs.
361 * The given buf can be any buf in the list.
362 */
363ExpBuf*
364ExpBufListLastBuf PARAMS ((b),
365 ExpBuf *b)
366{
367 for (; b->next != NULL; b = b->next)
368 ;
369 return b;
370}
371
372/*
373 * returns first buf in a list of bufs .
374 * The given buf can be any buf in the list
375 */
376ExpBuf*
377ExpBufListFirstBuf PARAMS ((b),
378 ExpBuf *b)
379{
380 for (; b->prev != NULL; b = b->prev)
381 ;
382 return b;
383}
384
385/*
386 * Allocates a Buf and allocates an attaches a
387 * data block of expBufDataBlkSizeG to that buffer.
388 * sets up the blk for writing in that the data start
389 * and data end point to the byte after the data blk.
390 */
391ExpBuf*
392ExpBufAllocBufAndData()
393{
394 ExpBuf *retVal;
395
396 retVal = ExpBufAllocBuf();
397
398 if (retVal == NULL)
399 return NULL;
400
401 retVal->readError = 0;
402 retVal->writeError = 0;
403 retVal->blkStart = ExpBufAllocData();
404
405 if (retVal->blkStart == NULL)
406 {
407 ExpBufFreeBuf (retVal);
408 return NULL;
409 }
410
411 retVal->next = NULL;
412 retVal->prev = NULL;
413 retVal->curr = retVal->blkEnd = retVal->dataStart = retVal->dataEnd =
414 retVal->blkStart + expBufDataBlkSizeG;
415
416 return retVal;
417} /* ExpBufAllocBufAndData */
418
419
420/*
421 * Frees ExpBuf's and associated data blocks after
422 * after (next ptr) and including the given buffer, b.
423 */
424void
425ExpBufFreeBufAndDataList PARAMS ((b),
426 ExpBuf *b)
427{
428 ExpBuf *tmp;
429
430 for (; b != NULL;)
431 {
432 tmp = b->next;
433 ExpBufFreeBufAndData (b);
434 b = tmp;
435 }
436} /* ExpBufFreeBufAndDataList */
437
438
439/*
440 * puts the given data in a buffer and sets it up for reading
441 * the data. This results in a "full" buffer with a data
442 * blk size of given data's len
443 */
444void
445ExpBufInstallDataInBuf PARAMS ((buf, data, len),
446 ExpBuf *buf _AND_
447 char *data _AND_
448 unsigned long int len)
449{
450 buf->readError = 0;
451 buf->writeError = 0;
452 buf->blkStart = buf->dataStart = buf->curr = data;
453 buf->next = NULL;
454 buf->prev = NULL;
455 buf->blkEnd = buf->dataEnd = data + len;
456} /* ExpBufInstallDataInBuf */
457
458
459
460/* Buf reading and writing routines follow */
461
462/* READ
463 * returns the next byte to be read without
464 * advancing the pointer. No check for end of
465 * data - this is lame
466 */
467unsigned char
468ExpBufPeekByte PARAMS ((b),
469 ExpBuf **b)
470{
471 if ((*b)->curr == (*b)->dataEnd)
472 (*b)->readError = 1;
473 return *(*b)->curr;
474} /* ExpBufPeek */
475
476#if TTBL
477
478/* READ
479 * returns a ptr to the next "len" bytes (contiguous).
480 * if "len" is greater than the available contiguous bytes
481 * len is set the the number of contig. bytes the returned
482 * ptr references. The next call to ExpBufGetSeg or other ExpBufGet
483 * routines will return a ptrsto the SAME bytes (ie curr is NOT advanced).
484 *
485 * Does not change the buffer
486 *
487 * if the value returned in the len param is zero or the
488 * returned char * is NULL then at end of data.
489 *
490 */
491char*
492ExpBufPeekSeg PARAMS ((b, len),
493 ExpBuf **b _AND_
494 unsigned long int *len)
495{
496 int bytesLeft;
497
498 if (ExpBufAtEod (*b))
499 {
500 *len = 0;
501 return NULL;
502 }
503
504 /* check for "buffer fault" and adjust "peeked" len */
505 if (((*b)->dataEnd - (*b)->curr) <= *len)
506 *len = bytesLeft;
507
508 return (*b)->curr;
509
510} /* ExpBufPeekSeg */
511
512
513/* READ
514 * copy the next len chars in the buffer to the given
515 * dst char string. The curr ptr in the buffer is
516 * NOT advanced so the next read will get the same bytes.
517 */
518int
519ExpBufPeekCopy PARAMS ((dst, b, len),
520 char *dst _AND_
521 ExpBuf **b _AND_
522 unsigned long int len)
523{
524 unsigned long int gotLen;
525 int totalGotLen = 0;
526 char *srcPtr;
527 ExpBuf *origBuf;
528
529 origBuf = *b;
530
531 gotLen = len;
532 while (1) /* optimize std path - eg only one ExpBufGetPeekSeg needed */
533 {
534 srcPtr = ExpBufPeekSeg (b, &gotLen);
535 memcpy (dst + totalGotLen, srcPtr, gotLen);
536
537 totalGotLen += gotLen;
538
539 if ((totalGotLen >= len) || ((*b)->next == NULL))
540 {
541 *b = origBuf;
542 return totalGotLen;
543 }
544
545 if (gotLen == 0) /* eod */
546 {
547 (*b)->readError = 1;
548 *b = origBuf;
549 return totalGotLen;
550 }
551
552 *b = (*b)->next;
553 /* get next buffer with valid data */
554 while (((*b)->next != NULL) && ExpBufHasNoData (*b))
555 *b = (*b)->next;
556
557 /* reset current pointer to beggining of data if nec */
558 (*b)->curr = (*b)->dataStart;
559
560 gotLen = len - totalGotLen;
561 }
562
563 /* not reached */
564
565} /* ExpBufPeekCopy */
566
567#endif /* TTBL */
568
569/* READ
570 * copy the next len chars in the buffer to the given
571 * dst char string. The curr ptr in the buffer is advanced
572 * appropriately
573 */
574int
575ExpBufCopy PARAMS ((dst, b, len),
576 char *dst _AND_
577 ExpBuf **b _AND_
578 unsigned long int len)
579{
580 unsigned long int gotLen;
581 int totalGotLen = 0;
582 char *srcPtr;
583
584 gotLen = len;
585 while (1) /* optimize std path - eg only one ExpBufGetSeg needed */
586 {
587 srcPtr = ExpBufGetSeg (b, &gotLen);
588 memcpy (dst + totalGotLen, srcPtr, gotLen);
589
590 totalGotLen += gotLen;
591
592 if (totalGotLen >= len)
593 return totalGotLen;
594
595 if (gotLen == 0) /* eod */
596 {
597 (*b)->readError = 1;
598 return totalGotLen;
599 }
600
601 gotLen = len - totalGotLen;
602 }
603
604 /* not reached */
605
606} /* ExpBufCopy */
607
608
609/*
610 * advance the curr ptr in the given buffer over the next
611 * len bytes
612 */
613void
614ExpBufSkip PARAMS ((b, len),
615 ExpBuf **b _AND_
616 unsigned long int len)
617{
618 unsigned long int lenRemaining;
619
620 lenRemaining = len;
621 while ((len > 0) && ExpBufGetSeg (b, &lenRemaining))
622 {
623 len -= lenRemaining;
624
625 if (lenRemaining == 0)
626 {
627 (*b)->readError = 1;
628 return;
629 }
630
631 lenRemaining = len;
632 }
633} /* ExpBufSkip */
634
635
636/* READ
637 * returns a ptr to the next "len" bytes (contiguous).
638 * if "len" is greater than the available contiguous bytes
639 * len is set the the number of contig. bytes the returned
640 * ptr references. Subsequent call to ExpBufGetSeg or other ExpBufGet
641 * routines will return ptrs to the following bytes (ie curr is advanced).
642 * Changes *b to pt to the next buffer and sets curr for the
643 * that buffer to dataStart if the current one has been totally read.
644 *
645 * if the value returned in the len param is zero or the
646 * returned char * is NULL then at end of data (eod)
647 *
648 */
649
650char*
651ExpBufGetSeg PARAMS ((b, len),
652 ExpBuf **b _AND_
653 unsigned long int *len)
654{
655 int bytesLeft;
656 char *retVal;
657
658 if (ExpBufAtEod (*b))
659 {
660 *len = 0;
661 return NULL;
662 }
663
664 bytesLeft = (*b)->dataEnd - (*b)->curr;
665 retVal = (*b)->curr;
666
667 /* check for "buffer fault" */
668 if (bytesLeft <= *len)
669 {
670 *len = bytesLeft;
671
672 if ((*b)->next != NULL)
673 {
674 *b = (*b)->next;
675
676 /* get next buffer with valid data */
677 while (((*b)->next != NULL) && ExpBufHasNoData (*b))
678 *b = (*b)->next;
679
680 /* reset current pointer to beggining of data if nec */
681 (*b)->curr = (*b)->dataStart;
682 }
683 else
684 (*b)->curr += *len;
685 }
686 else
687 (*b)->curr += *len;
688
689 return retVal;
690
691} /* ExpBufGetSeg */
692
693
694
695/*
696 * WRITE
697 * Copies len bytes from the data pointer into the given buffer
698 *
699 * FILLS EXP_BUFFERS BACKWARDS! from the end of the data to the beginning
700 * LINKS BUFFERS BACKWARDS! if a buf is full it allocs another an
701 * puts it at the HEAD of the buffer list
702 *
703 * changes *b to pt to the new "prev" buffer if the current one
704 * has been totally filled
705 * Rvs is for REVERSE!
706 *
707 * modifies the dataStart pointer to reflect the new data
708 */
709
710void
711ExpBufPutSegRvs PARAMS ((b, data, len),
712 ExpBuf **b _AND_
713 char *data _AND_
714 unsigned long int len)
715{
716 int bytesLeft;
717 ExpBuf *buf;
718 char *dataPtr;
719
720 buf = *b;
721
722 if (buf->writeError)
723 return;
724
725 bytesLeft = buf->dataStart - buf->blkStart;
726 dataPtr = data + len; /* pts to end of data to be written */
727
728 /* optimize fast path */
729
730 do
731 {
732 if (bytesLeft > len) /* enough room in this buffer for write */
733 {
734 buf->dataStart -= len;
735 memcpy (buf->dataStart, data, len);
736 break; /* this is the normal exit from this loop */
737 }
738 else
739 {
740 /*
741 * going to fill this buffer completely,
742 * so alloc other one (only if one is not
743 * already linked in)
744 */
745 dataPtr = dataPtr - bytesLeft;
746 buf->dataStart = buf->blkStart;
747 memcpy (buf->dataStart, dataPtr, bytesLeft);
748
749 len -= bytesLeft;
750
751 if (buf->prev == NULL)
752 {
753 /* alloc & insert new buf at head of buffer list */
754 buf = ExpBufAllocBufAndData();
755
756 if (buf == NULL)
757 {
758 (*b)->writeError = 1;
759 return;
760 }
761
762 buf->next = *b;
763 (*b)->prev = buf;
764 }
765 else
766 buf = buf->prev;
767
768 *b = buf; /* update head of list */
769
770 bytesLeft = buf->dataStart - buf->blkStart;
771 }
772 }
773 while (1);
774
775 /* not reached */
776
777} /* ExpBufPutSegRvs */
778
779
780
781/*
782 * returns the next byte and advances the curr ptr by one.
783 * sets the readError flag if there is no byte to read
784 * (ie at end of data)
785 */
786unsigned char
787ExpBufGetByte PARAMS ((b),
788 ExpBuf **b)
789{
790 unsigned char retVal;
791
792
793 if (ExpBufAtEod (*b))
794 {
795 (*b)->readError = 1;
796 return (unsigned char)0;
797 }
798
799 retVal = *(*b)->curr++;
800
801 /* "buffer fault" - if end of this buf, go on to next, if any */
802 if (ExpBufAtEod (*b) && ((*b)->next != NULL))
803 {
804 *b = (*b)->next;
805
806 /* get next buffer with valid data */
807 while (((*b)->next != NULL) && ExpBufHasNoData (*b))
808 *b = (*b)->next;
809
810 /* reset current pointer to beggining of data if nec */
811 (*b)->curr = (*b)->dataStart;
812 }
813
814 return retVal;
815
816} /* ExpBufGetByte */
817
818
819/* WRITE
820 * Puts a single octet into the buffer
821 * writes in reverse.
822 * allocates new buffers as nec - may change
823 * (*b) to new buffer since writing backwards
824 */
825void
826ExpBufPutByteRvs PARAMS ((b, byte),
827 ExpBuf **b _AND_
828 unsigned char byte)
829{
830 ExpBuf *new;
831
832 if ((*b)->writeError)
833 return;
834
835 *(--(*b)->dataStart) = byte;
836
837 /*
838 * check if buffer is full and alloc new one if nec
839 * and insert it before this one since writing backwards
840 */
841 if (ExpBufFull (*b))
842 {
843 if ((*b)->prev == NULL)
844 {
845 /*
846 * no prev buf so alloc & insert
847 * new buf as head of buffer list
848 */
849 new = ExpBufAllocBufAndData();
850 if (new == NULL)
851 {
852 (*b)->writeError = 1;
853 return;
854 }
855
856 new->next = *b;
857 (*b)->prev = new;
858 *b = new;
859 }
860 else
861 {
862 (*b) = (*b)->prev;
863 ExpBufResetInWriteRvsMode (*b);
864 }
865
866 }
867} /* ExpBufPutByteRvs */
868
869
870void
871ExpBufCopyToFile PARAMS ((b, f),
872 ExpBuf *b _AND_
873 FILE *f)
874{
875 long int writeLen;
876
877 b = ExpBufListFirstBuf (b);
878
879 for ( ; b != NULL; b = ExpBufNext (b))
880 {
881 writeLen = fwrite (ExpBufDataPtr (b), sizeof (char), ExpBufDataSize (b), f);
882
883 if (writeLen != ExpBufDataSize (b))
884 fprintf (stderr, "ExpBufCopyToFile: error during writing\n");
885 }
886}
887
888#else /* !USE_EXP_BUF */
889
890#ifdef __alpha
891static void dummy()
892{
893}
894#endif
895
896#endif /* USE_EXP_BUF */