chiark / gitweb /
midas class
[ypp-sc-tools.db-live.git] / yarrg / common.c
1 /*
2  * Utility functions
3  */
4 /*
5  *  This is part of ypp-sc-tools, a set of third-party tools for assisting
6  *  players of Yohoho Puzzle Pirates.
7  * 
8  *  Copyright (C) 2009 Ian Jackson <ijackson@chiark.greenend.org.uk>
9  * 
10  *  This program is free software: you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation, either version 3 of the License, or
13  *  (at your option) any later version.
14  * 
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  * 
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  * 
23  *  Yohoho and Puzzle Pirates are probably trademarks of Three Rings and
24  *  are used without permission.  This program is not endorsed or
25  *  sponsored by Three Rings.
26  */
27
28 #include "common.h"
29
30 void *mmalloc(size_t sz) {
31   void *r;
32   if (!sz) return 0;
33   sysassert( r= malloc(sz) );
34   return r;
35 }
36 void *mcalloc(size_t sz) {
37   void *r;
38   if (!sz) return 0;
39   sysassert( r= malloc(sz) );
40   memset(r, 0, sz);
41   return r;
42 }
43 void *mrealloc(void *p, size_t sz) {
44   assert(sz);
45   void *r;
46   sysassert( r= realloc(p,sz) );
47   return r;
48 }
49
50 DEFINE_VWRAPPERF(, progress, )
51 DEFINE_VWRAPPERF(, progress_log, )
52 DEFINE_VWRAPPERF(, progress_spinner, )
53 DEFINE_VWRAPPERF(, warning, )
54 DEFINE_VWRAPPERF(, fatal, NORET)
55
56 static int last_progress_len;
57
58 static void vprogress_core(int spinner, const char *fmt, va_list al) {
59   int r;
60   
61   if (o_quiet) return;
62   if (!debug_flags && !isatty(2)) return;
63   
64   if (last_progress_len)
65     putc('\r',stderr);
66
67   r= vfprintf(stderr,fmt,al);
68
69   if (spinner) {
70     putc(spinner,stderr);
71     r++;
72   }
73
74   if (r < last_progress_len) {
75     fprintf(stderr,"%*s", last_progress_len - r, "");
76     if (!r) putc('\r', stderr);
77     else while (last_progress_len-- > r) putc('\b',stderr);
78   }
79   last_progress_len= r;
80
81   if (ferror(stderr) || fflush(stderr)) _exit(16);
82 }
83    
84 void vprogress(const char *fmt, va_list al) { vprogress_core(0,fmt,al); }
85 void vprogress_spinner(const char *fmt, va_list al) {
86   static const char spinchars[]="/-\\";
87   static int spinner;
88
89   vprogress_core(spinchars[spinner],fmt,al);
90   spinner++;
91   spinner %= (sizeof(spinchars)-1);
92 }
93
94 void vprogress_log(const char *fmt, va_list al) {
95   if (o_quiet) return;
96   
97   progress("");
98   vfprintf(stderr,fmt,al);
99   putc('\n',stderr);
100   fflush(stderr);
101 }
102
103 void vwarning(const char *fmt, va_list al) {
104   progress("");
105   fputs("Warning: ",stderr);
106   vfprintf(stderr,fmt,al);
107   fputs("\n",stderr);
108   fflush(stderr);
109 }
110
111 void vfatal(const char *fmt, va_list al) {
112   progress("");
113   fputs("\n\nFatal error: ",stderr);
114   vfprintf(stderr,fmt,al);
115   fflush(stderr);
116   fputs("\n\n",stderr);
117   _exit(4);
118 }
119
120 void sysassert_fail(const char *file, int line, const char *what) {
121   int e= errno;
122   progress("");
123   fprintf(stderr,
124           "\nfatal operational error:\n"
125           " unsuccessful execution of: %s\n"
126           " %s:%d: %s\n\n",
127           what, file,line, strerror(e));
128   _exit(16);
129 }
130
131 void waitpid_check_exitstatus(pid_t pid, const char *what, int sigpipeok) { 
132   pid_t got;
133   int st;
134   for (;;) {
135     got= waitpid(pid, &st, 0);
136     if (pid==-1) { sysassert(errno==EINTR); continue; }
137     break;
138   }
139   sysassert( got==pid );
140
141   if (WIFEXITED(st)) {
142     if (WEXITSTATUS(st))
143       fatal("%s failed with nonzero exit status %d",
144             what, WEXITSTATUS(st));
145   } else if (WIFSIGNALED(st)) {
146     if (!sigpipeok || WTERMSIG(st) != SIGPIPE)
147       fatal("%s died due to signal %s%s", what,
148             strsignal(WTERMSIG(st)), WCOREDUMP(st)?" (core dumped)":"");
149   } else {
150     fatal("%s gave strange wait status %d", what, st);
151   }
152 }
153
154 char *masprintf(const char *fmt, ...) {
155   char *r;
156   va_list al;
157   va_start(al,fmt);
158   sysassert( vasprintf(&r,fmt,al) >= 0);
159   sysassert(r);
160   va_end(al);
161   return r;
162 }
163
164 unsigned debug_flags;
165
166 void debug_flush(void) {
167   sysassert(!ferror(debug));
168   sysassert(!fflush(debug));
169 }