VirtualBox

source: kBuild/trunk/src/sed/lib/utils.c

Last change on this file was 3490, checked in by bird, 4 years ago

sed: Darwin build fix.

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

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