VirtualBox

source: kBuild/vendor/sed/current/lib/utils.c

Last change on this file was 599, checked in by bird, 18 years ago

GNU sed 4.1.5.

File size: 9.9 KB
Line 
1/* Functions from hack's utils library.
2 Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003
3 Free Software Foundation, Inc.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19#include "config.h"
20
21#include <stdio.h>
22
23#include <errno.h>
24#ifndef errno
25 extern int errno;
26#endif
27
28#ifdef HAVE_STRINGS_H
29# include <strings.h>
30#else
31# include <string.h>
32#endif /* HAVE_STRINGS_H */
33
34#ifdef HAVE_STDLIB_H
35# include <stdlib.h>
36#endif /* HAVE_STDLIB_H */
37
38#include "utils.h"
39
40const char *myname;
41
42/* Store information about files opened with ck_fopen
43 so that error messages from ck_fread, ck_fwrite, etc. can print the
44 name of the file that had the error */
45
46struct open_file
47 {
48 FILE *fp;
49 char *name;
50 struct open_file *link;
51 unsigned temp : 1;
52 };
53
54static struct open_file *open_files = NULL;
55static void do_ck_fclose P_((FILE *fp));
56
57/* Print an error message and exit */
58#if !defined __STDC__ || !(__STDC__-0)
59# include <varargs.h>
60# define VSTART(l,a) va_start(l)
61void
62panic(str, va_alist)
63 char *str;
64 va_dcl
65#else /*__STDC__*/
66# include <stdarg.h>
67# define VSTART(l,a) va_start(l, a)
68void
69panic(const char *str, ...)
70#endif /* __STDC__ */
71{
72 va_list iggy;
73
74 fprintf(stderr, "%s: ", myname);
75 VSTART(iggy, str);
76#ifndef HAVE_VPRINTF
77# ifndef HAVE_DOPRNT
78 fputs(str, stderr); /* not great, but perhaps better than nothing... */
79# else /* HAVE_DOPRNT */
80 _doprnt(str, &iggy, stderr);
81# endif /* HAVE_DOPRNT */
82#else /* HAVE_VFPRINTF */
83 vfprintf(stderr, str, iggy);
84#endif /* HAVE_VFPRINTF */
85 va_end(iggy);
86 putc('\n', stderr);
87
88 /* Unlink the temporary files. */
89 while (open_files)
90 {
91 if (open_files->temp)
92 {
93 int fd = fileno (open_files->fp);
94 fclose (open_files->fp);
95 errno = 0;
96 unlink (open_files->name);
97 if (errno != 0)
98 fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno));
99 }
100
101 open_files = open_files->link;
102 }
103
104 exit(4);
105}
106
107
108
109/* Internal routine to get a filename from open_files */
110static const char *utils_fp_name P_((FILE *fp));
111static const char *
112utils_fp_name(fp)
113 FILE *fp;
114{
115 struct open_file *p;
116
117 for (p=open_files; p; p=p->link)
118 if (p->fp == fp)
119 return p->name;
120 if (fp == stdin)
121 return "stdin";
122 else if (fp == stdout)
123 return "stdout";
124 else if (fp == stderr)
125 return "stderr";
126
127 return "<unknown>";
128}
129
130/* Panic on failing fopen */
131FILE *
132ck_fopen(name, mode, fail)
133 const char *name;
134 const char *mode;
135 bool fail;
136{
137 FILE *fp;
138 struct open_file *p;
139
140 fp = fopen (name, mode);
141 if (!fp)
142 {
143 if (fail)
144 panic(_("couldn't open file %s: %s"), name, strerror(errno));
145
146 return NULL;
147 }
148
149 for (p=open_files; p; p=p->link)
150 {
151 if (fp == p->fp)
152 {
153 FREE(p->name);
154 break;
155 }
156 }
157 if (!p)
158 {
159 p = MALLOC(1, struct open_file);
160 p->link = open_files;
161 open_files = p;
162 }
163 p->name = ck_strdup(name);
164 p->fp = fp;
165 p->temp = false;
166 return fp;
167}
168
169FILE *
170ck_mkstemp (p_filename, tmpdir, base)
171 char **p_filename;
172 char *base, *tmpdir;
173{
174 char *template;
175 FILE *fp;
176 int fd;
177 struct open_file *p;
178
179 if (tmpdir == NULL)
180 tmpdir = getenv("TMPDIR");
181 if (tmpdir == NULL)
182 {
183 tmpdir = getenv("TMP");
184 if (tmpdir == NULL)
185#ifdef P_tmpdir
186 tmpdir = P_tmpdir;
187#else
188 tmpdir = "/tmp";
189#endif
190 }
191
192 template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
193 sprintf (template, "%s/%sXXXXXX", tmpdir, base);
194
195 fd = mkstemp (template);
196 if (fd == -1)
197 panic(_("couldn't open temporary file %s: %s"), template, strerror(errno));
198
199 *p_filename = template;
200 fp = fdopen (fd, "w");
201
202 p = MALLOC(1, struct open_file);
203 p->name = ck_strdup (template);
204 p->fp = fp;
205 p->temp = true;
206 p->link = open_files;
207 open_files = p;
208 return fp;
209}
210
211/* Panic on failing fwrite */
212void
213ck_fwrite(ptr, size, nmemb, stream)
214 const VOID *ptr;
215 size_t size;
216 size_t nmemb;
217 FILE *stream;
218{
219 clearerr(stream);
220 if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
221 panic(ngettext("couldn't write %d item to %s: %s",
222 "couldn't write %d items to %s: %s", nmemb),
223 nmemb, utils_fp_name(stream), strerror(errno));
224}
225
226/* Panic on failing fread */
227size_t
228ck_fread(ptr, size, nmemb, stream)
229 VOID *ptr;
230 size_t size;
231 size_t nmemb;
232 FILE *stream;
233{
234 clearerr(stream);
235 if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream))
236 panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
237
238 return nmemb;
239}
240
241size_t
242ck_getline(text, buflen, stream)
243 char **text;
244 size_t *buflen;
245 FILE *stream;
246{
247 int result;
248 if (!ferror (stream))
249 result = getline (text, buflen, stream);
250
251 if (ferror (stream))
252 panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
253
254 return result;
255}
256
257/* Panic on failing fflush */
258void
259ck_fflush(stream)
260 FILE *stream;
261{
262 clearerr(stream);
263 if (fflush(stream) == EOF && errno != EBADF)
264 panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno));
265}
266
267/* Panic on failing fclose */
268void
269ck_fclose(stream)
270 FILE *stream;
271{
272 struct open_file r;
273 struct open_file *prev;
274 struct open_file *cur;
275
276 /* a NULL stream means to close all files */
277 r.link = open_files;
278 prev = &r;
279 while ( (cur = prev->link) )
280 {
281 if (!stream || stream == cur->fp)
282 {
283 do_ck_fclose (cur->fp);
284 prev->link = cur->link;
285 FREE(cur->name);
286 FREE(cur);
287 }
288 else
289 prev = cur;
290 }
291
292 open_files = r.link;
293
294 /* Also care about stdout, because if it is redirected the
295 last output operations might fail and it is important
296 to signal this as an error (perhaps to make). */
297 if (!stream)
298 {
299 do_ck_fclose (stdout);
300 do_ck_fclose (stderr);
301 }
302}
303
304/* Close a single file. */
305void
306do_ck_fclose(fp)
307 FILE *fp;
308{
309 int fd;
310 ck_fflush(fp);
311 clearerr(fp);
312
313 /* We want to execute both arms, so use | not ||. */
314 if (fclose(fp) == EOF)
315 panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno));
316}
317
318
319
320/* Panic on failing rename */
321void
322ck_rename (from, to, unlink_if_fail)
323 const char *from, *to;
324 const char *unlink_if_fail;
325{
326 int rd = rename (from, to);
327 if (rd != -1)
328 return;
329
330 if (unlink_if_fail)
331 {
332 int save_errno = errno;
333 errno = 0;
334 unlink (unlink_if_fail);
335
336 /* Failure to remove the temporary file is more severe, so trigger it first. */
337 if (errno != 0)
338 panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
339
340 errno = save_errno;
341 }
342
343 panic (_("cannot rename %s: %s"), from, strerror (errno));
344}
345
346
347
348
349
350/* Panic on failing malloc */
351VOID *
352ck_malloc(size)
353 size_t size;
354{
355 VOID *ret = calloc(1, size ? size : 1);
356 if (!ret)
357 panic("couldn't allocate memory");
358 return ret;
359}
360
361/* Panic on failing malloc */
362VOID *
363xmalloc(size)
364 size_t size;
365{
366 return ck_malloc(size);
367}
368
369/* Panic on failing realloc */
370VOID *
371ck_realloc(ptr, size)
372 VOID *ptr;
373 size_t size;
374{
375 VOID *ret;
376
377 if (size == 0)
378 {
379 FREE(ptr);
380 return NULL;
381 }
382 if (!ptr)
383 return ck_malloc(size);
384 ret = realloc(ptr, size);
385 if (!ret)
386 panic("couldn't re-allocate memory");
387 return ret;
388}
389
390/* Return a malloc()'d copy of a string */
391char *
392ck_strdup(str)
393 const char *str;
394{
395 char *ret = MALLOC(strlen(str)+1, char);
396 return strcpy(ret, str);
397}
398
399/* Return a malloc()'d copy of a block of memory */
400VOID *
401ck_memdup(buf, len)
402 const VOID *buf;
403 size_t len;
404{
405 VOID *ret = ck_malloc(len);
406 return memcpy(ret, buf, len);
407}
408
409/* Release a malloc'd block of memory */
410void
411ck_free(ptr)
412 VOID *ptr;
413{
414 if (ptr)
415 free(ptr);
416}
417
418
419
420/* Implement a variable sized buffer of `stuff'. We don't know what it is,
421nor do we care, as long as it doesn't mind being aligned by malloc. */
422
423struct buffer
424 {
425 size_t allocated;
426 size_t length;
427 char *b;
428 };
429
430#define MIN_ALLOCATE 50
431
432struct buffer *
433init_buffer()
434{
435 struct buffer *b = MALLOC(1, struct buffer);
436 b->b = MALLOC(MIN_ALLOCATE, char);
437 b->allocated = MIN_ALLOCATE;
438 b->length = 0;
439 return b;
440}
441
442char *
443get_buffer(b)
444 struct buffer *b;
445{
446 return b->b;
447}
448
449size_t
450size_buffer(b)
451 struct buffer *b;
452{
453 return b->length;
454}
455
456static void resize_buffer P_((struct buffer *b, size_t newlen));
457static void
458resize_buffer(b, newlen)
459 struct buffer *b;
460 size_t newlen;
461{
462 char *try = NULL;
463 size_t alen = b->allocated;
464
465 if (newlen <= alen)
466 return;
467 alen *= 2;
468 if (newlen < alen)
469 try = realloc(b->b, alen); /* Note: *not* the REALLOC() macro! */
470 if (!try)
471 {
472 alen = newlen;
473 try = REALLOC(b->b, alen, char);
474 }
475 b->allocated = alen;
476 b->b = try;
477}
478
479char *
480add_buffer(b, p, n)
481 struct buffer *b;
482 const char *p;
483 size_t n;
484{
485 char *result;
486 if (b->allocated - b->length < n)
487 resize_buffer(b, b->length+n);
488 result = memcpy(b->b + b->length, p, n);
489 b->length += n;
490 return result;
491}
492
493char *
494add1_buffer(b, c)
495 struct buffer *b;
496 int c;
497{
498 /* This special case should be kept cheap;
499 * don't make it just a mere convenience
500 * wrapper for add_buffer() -- even "builtin"
501 * versions of memcpy(a, b, 1) can become
502 * expensive when called too often.
503 */
504 if (c != EOF)
505 {
506 char *result;
507 if (b->allocated - b->length < 1)
508 resize_buffer(b, b->length+1);
509 result = b->b + b->length++;
510 *result = c;
511 return result;
512 }
513
514 return NULL;
515}
516
517void
518free_buffer(b)
519 struct buffer *b;
520{
521 if (b)
522 FREE(b->b);
523 FREE(b);
524}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette