VirtualBox

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

Last change on this file since 3432 was 3188, checked in by bird, 7 years ago

kmk,lib,kWorker: Console output on windows cleanups.

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