mescc: Add proper includes.
[mes.git] / lib / libmes.c
1 /* -*-comment-start: "//";comment-end:""-*-
2  * Mes --- Maxwell Equations of Software
3  * Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
4  *
5  * This file is part of Mes.
6  *
7  * Mes is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or (at
10  * your option) any later version.
11  *
12  * Mes is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with Mes.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <libmes.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 int
27 isdigit (int c)
28 {
29   return c >= '0' && c <= '9';
30 }
31
32 int
33 isxdigit (int c)
34 {
35   return isdigit (c) || (c >= 'a' && c <= 'f');
36 }
37
38 int
39 isspace (int c)
40 {
41   return (c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || c == ' ');
42 }
43
44 int
45 isnumber (int c, int base)
46 {
47   if (base == 2)
48     return (c >= '0') && (c <= '1');
49   if (base == 8)
50     return (c >= '0') && (c <= '7');
51   if (base == 10)
52     return isdigit (c);
53   if (base == 16)
54     return isxdigit (c);
55 }
56
57 int
58 abtoi (char const **p, int base)
59 {
60   char const *s = *p;
61   int i = 0;
62   int sign = 1;
63   if (!base) base = 10;
64   if (*s && *s == '-')
65     {
66       sign = -1;
67       s++;
68     }
69   while (isnumber (*s, base))
70     {
71       i *= base;
72       int m = *s > '9' ? 'a' - 10 : '0';
73       i += *s - m;
74       s++;
75     }
76   *p = s;
77   return i * sign;
78 }
79
80 int
81 atoi (char const *s)
82 {
83   char const *p = s;
84   return abtoi (&p, 0);
85 }
86
87 char const*
88 number_to_ascii (int x, int base, int signed_p)
89 {
90   static char itoa_buf[12];
91   char *p = itoa_buf + 11;
92   *p-- = 0;
93
94   int sign = 0;
95   unsigned u = x;
96   if (signed_p && x < 0)
97     {
98       sign = 1;
99       u = -x;
100     }
101
102   do
103      {
104        int i = u % base;
105        *p-- = i > 9 ? 'a' + i - 10 : '0' + i;
106        u = u / base;
107      } while (u);
108
109   if (sign && *(p + 1) != '0')
110     *p-- = '-';
111
112   return p+1;
113 }
114
115 char const*
116 itoab (int x, int base)
117 {
118   return number_to_ascii (x, base, 1);
119 }
120
121 char const*
122 itoa (int x)
123 {
124   return number_to_ascii (x, 10, 1);
125 }
126
127 char const*
128 utoa (unsigned x)
129 {
130   return number_to_ascii (x, 10, 0);
131 }
132
133 int _ungetc_pos = -1;
134 int _ungetc_fd = -1;
135 char _ungetc_buf[10];
136
137 int
138 fdgetc (int fd)
139 {
140   char c;
141   int i;
142   if (_ungetc_pos == -1)
143     {
144       int r = read (fd, &c, 1);
145       if (r < 1)
146         return -1;
147       i = c;
148    }
149   else
150     {
151       i = _ungetc_buf[_ungetc_pos];
152       if (_ungetc_fd != fd && i == 10)
153         {
154           // FIXME: Nyacc's ungetc exposes harmless libmec.c bug
155           // we need one unget position per FD
156           _ungetc_pos = -1;
157           _ungetc_fd = -1;
158           return fdgetc (fd);
159         }
160       else if (_ungetc_fd != fd)
161         {
162           eputs (" ***MES LIB C*** fdgetc ungetc conflict unget-fd=");
163           eputs (itoa (_ungetc_fd));
164           eputs (", fdgetc-fd=");
165           eputs (itoa (fd));
166           eputs (", c=");
167           eputs (itoa ( _ungetc_buf[_ungetc_pos]));
168           eputs ("\n");
169           exit (1);
170         }
171       i = _ungetc_buf[_ungetc_pos];
172       _ungetc_pos -= 1;
173       if (_ungetc_pos == -1)
174         _ungetc_fd = -1;
175      }
176   if (i < 0)
177     i += 256;
178
179   return i;
180 }
181
182 int
183 fdputc (int c, int fd)
184 {
185   write (fd, (char*)&c, 1);
186   return 0;
187 }
188
189 int
190 fdputs (char const* s, int fd)
191 {
192   int i = strlen (s);
193   write (fd, s, i);
194   return 0;
195 }
196
197 int
198 fdungetc (int c, int fd)
199 {
200   if (c == -1)
201     return c;
202   if (_ungetc_pos == -1)
203     _ungetc_fd = fd;
204   else if (_ungetc_fd != fd)
205     {
206       eputs (" ***MES LIB C*** fdungetc ungetc conflict unget-fd=");
207       eputs (itoa (_ungetc_fd));
208       eputs (", fdungetc-fd=");
209       eputs (itoa (fd));
210       eputs ("\n");
211       exit (1);
212     }
213   _ungetc_pos++;
214   _ungetc_buf[_ungetc_pos] = c;
215   return c;
216 }
217
218 int
219 _fdungetc_p (int fd)
220 {
221   return _ungetc_pos > -1;
222 }
223
224 #if POSIX || __x86_64__
225 #define STDERR 2
226 int
227 eputs (char const* s)
228 {
229   int i = strlen (s);
230   write (STDERR, s, i);
231   return 0;
232 }
233 #endif
234
235 int
236 eputc (int c)
237 {
238   return fdputc (c, STDERR);
239 }