chiark / gitweb /
WIP per-island-pair trades
[ypp-sc-tools.main.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 *mrealloc(void *p, size_t sz) {
37   assert(sz);
38   void *r;
39   sysassert( r= realloc(p,sz) );
40   return r;
41 }
42
43 DEFINE_VWRAPPERF(, progress, )
44 DEFINE_VWRAPPERF(, progress_log, )
45 DEFINE_VWRAPPERF(, progress_spinner, )
46 DEFINE_VWRAPPERF(, warning, )
47 DEFINE_VWRAPPERF(, fatal, NORET)
48
49 static int last_progress_len;
50
51 static void vprogress_core(int spinner, const char *fmt, va_list al) {
52   int r;
53   
54   if (o_quiet) return;
55   if (!debug_flags && !isatty(2)) return;
56   
57   if (last_progress_len)
58     putc('\r',stderr);
59
60   r= vfprintf(stderr,fmt,al);
61
62   if (spinner) {
63     putc(spinner,stderr);
64     r++;
65   }
66
67   if (r < last_progress_len) {
68     fprintf(stderr,"%*s", last_progress_len - r, "");
69     if (!r) putc('\r', stderr);
70     else while (last_progress_len-- > r) putc('\b',stderr);
71   }
72   last_progress_len= r;
73
74   if (ferror(stderr) || fflush(stderr)) _exit(16);
75 }
76    
77 void vprogress(const char *fmt, va_list al) { vprogress_core(0,fmt,al); }
78 void vprogress_spinner(const char *fmt, va_list al) {
79   static const char spinchars[]="/-\\";
80   static int spinner;
81
82   vprogress_core(spinchars[spinner],fmt,al);
83   spinner++;
84   spinner %= (sizeof(spinchars)-1);
85 }
86
87 void vprogress_log(const char *fmt, va_list al) {
88   if (o_quiet) return;
89   
90   progress("");
91   vfprintf(stderr,fmt,al);
92   putc('\n',stderr);
93   fflush(stderr);
94 }
95
96 void vwarning(const char *fmt, va_list al) {
97   progress("");
98   fputs("Warning: ",stderr);
99   vfprintf(stderr,fmt,al);
100   fputs("\n",stderr);
101   fflush(stderr);
102 }
103
104 void vfatal(const char *fmt, va_list al) {
105   progress("");
106   fputs("\n\nFatal error: ",stderr);
107   vfprintf(stderr,fmt,al);
108   fflush(stderr);
109   fputs("\n\n",stderr);
110   _exit(4);
111 }
112
113 void sysassert_fail(const char *file, int line, const char *what) {
114   int e= errno;
115   progress("");
116   fprintf(stderr,
117           "\nfatal operational error:\n"
118           " unsuccessful execution of: %s\n"
119           " %s:%d: %s\n\n",
120           what, file,line, strerror(e));
121   _exit(16);
122 }
123
124 void waitpid_check_exitstatus(pid_t pid, const char *what, int sigpipeok) { 
125   pid_t got;
126   int st;
127   for (;;) {
128     got= waitpid(pid, &st, 0);
129     if (pid==-1) { sysassert(errno==EINTR); continue; }
130     break;
131   }
132   sysassert( got==pid );
133
134   if (WIFEXITED(st)) {
135     if (WEXITSTATUS(st))
136       fatal("%s failed with nonzero exit status %d",
137             what, WEXITSTATUS(st));
138   } else if (WIFSIGNALED(st)) {
139     if (!sigpipeok || WTERMSIG(st) != SIGPIPE)
140       fatal("%s died due to signal %s%s", what,
141             strsignal(WTERMSIG(st)), WCOREDUMP(st)?" (core dumped)":"");
142   } else {
143     fatal("%s gave strange wait status %d", what, st);
144   }
145 }
146
147 char *masprintf(const char *fmt, ...) {
148   char *r;
149   va_list al;
150   va_start(al,fmt);
151   sysassert( vasprintf(&r,fmt,al) >= 0);
152   sysassert(r);
153   va_end(al);
154   return r;
155 }
156
157
158 unsigned debug_flags;
159
160 void debug_flush(void) {
161   sysassert(!ferror(debug));
162   sysassert(!fflush(debug));
163 }