1/* buffer.c
2   Manipulate buffers used to hold strings.
3
4   Copyright (C) 1992, 1993, 2002 Ian Lance Taylor
5
6   This file is part of Taylor UUCP.
7
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Library General Public License
10   as published by the Free Software Foundation; either version 2 of
11   the License, or (at your option) any later version.
12
13   This library is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Library General Public License for more details.
17
18   You should have received a copy of the GNU Library General Public
19   License along with this library; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucp.h"
26
27#include "uudefs.h"
28
29/* Define MALLOC_BUFFERS when compiling this file in order to more
30   effectively use a debugging malloc library.  */
31
32#ifndef MALLOC_BUFFERS
33
34/* We keep a linked list of buffers.  The union is a hack because the
35   default definition of offsetof, in uucp.h, takes the address of the
36   field, and some C compilers will not let you take the address of an
37   array.  */
38
39struct sbuf
40{
41  struct sbuf *qnext;
42  size_t c;
43  union
44    {
45      char ab[4];
46      char bdummy;
47    }
48  u;
49};
50
51static struct sbuf *qBlist;
52
53/* Get a buffer of a given size.  The buffer is returned with the
54   ubuffree function.  */
55
56char *
57zbufalc (c)
58     size_t c;
59{
60  register struct sbuf *q;
61
62  if (qBlist == NULL)
63    {
64      q = (struct sbuf *) xmalloc (sizeof (struct sbuf) + c - 4);
65      q->c = c;
66    }
67  else
68    {
69      q = qBlist;
70      qBlist = q->qnext;
71      if (q->c < c)
72	{
73	  q = (struct sbuf *) xrealloc ((pointer) q,
74					sizeof (struct sbuf) + c - 4);
75	  q->c = c;
76	}
77    }
78  return q->u.ab;
79}
80
81/* Free up a buffer back onto the linked list.  */
82
83void
84ubuffree (z)
85     char *z;
86{
87  struct sbuf *q;
88  /* The type of ioff should be size_t, but making it int avoids a bug
89     in some versions of the HP/UX compiler, and will always work.  */
90  int ioff;
91
92  if (z == NULL)
93    return;
94  ioff = offsetof (struct sbuf, u);
95  q = (struct sbuf *) (pointer) (z - ioff);
96
97#ifdef DEBUG_BUFFER
98  {
99    struct sbuf *qlook;
100
101    for (qlook = qBlist; qlook != NULL; qlook = qlook->qnext)
102      {
103	if (qlook == q)
104	  {
105	    ulog (LOG_ERROR, "ubuffree: Attempt to free buffer twice");
106	    abort ();
107	  }
108      }
109  }
110#endif
111
112  q->qnext = qBlist;
113  qBlist = q;
114}
115
116#else /* MALLOC_BUFFERS */
117
118char *
119zbufalc (c)
120     size_t c;
121{
122  return (char *) xmalloc (c);
123}
124
125/* Free up a buffer back onto the linked list.  */
126
127void
128ubuffree (z)
129     char *z;
130{
131  free (z);
132}
133
134#endif /* MALLOC_BUFFERS */
135
136/* Get a buffer holding a given string.  */
137
138char *
139zbufcpy (z)
140     const char *z;
141{
142  size_t csize;
143  char *zret;
144
145  if (z == NULL)
146    return NULL;
147  csize = strlen (z) + 1;
148  zret = zbufalc (csize);
149  memcpy (zret, z, csize);
150  return zret;
151}
152