chiark / gitweb /
Provide a decent interface for finding out about the audio cache and
[jog] / aunum.c
1 /* -*-c-*-
2  *
3  * $Id: aunum.c,v 1.1 2002/02/02 19:16:28 mdw Exp $
4  *
5  * Reading numbers to audio output
6  *
7  * (c) 2002 Mark Wooding
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of Jog: Programming for a jogging machine.
13  *
14  * Jog is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * Jog is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with Jog; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: aunum.c,v $
32  * Revision 1.1  2002/02/02 19:16:28  mdw
33  * New audio subsystem.
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #ifdef HAVE_CONFIG_H
40 #  include "config.h"
41 #endif
42
43 #include <assert.h>
44 #include <ctype.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #include <mLib/dstr.h>
50
51 #include "au.h"
52
53 /*----- Main code ---------------------------------------------------------*/
54
55 /* --- @digit@ --- *
56  *
57  * Arguments:   @char x@ = single digit to read
58  *
59  * Returns:     ---
60  *
61  * Use:         Reads a single digit.
62  */
63
64 static void digit(int x)
65 {
66   static char tagbuf[4] = "n-?";
67   tagbuf[2] = x;
68   au_play(tagbuf);
69 }
70
71 /* --- @digits@ --- *
72  *
73  * Arguments:   @const char *p@ = pointer to digits
74  *              @size_t n@ = number of digits
75  *
76  * Returns:     ---
77  *
78  * Use:         Reads a sequence of digits.
79  */
80
81 static void digits(const char *p, size_t n)
82 {
83   while (n) {
84     digit(*p++);
85     n--;
86   }
87 }
88
89 /* --- @lasttwo@ --- *
90  *
91  * Arguments:   @const char *p@ = pointer to digits
92  *              @size_t n@ = number of digits
93  *              @unsigned f@ = flags
94  *
95  * Returns:     Nonzero if the number was nonzero.
96  *
97  * Use:         Reads out a number of no more than two digits.
98  */
99
100 #define f_and 1u
101
102 static int lasttwo(const char *p, size_t n, unsigned f)
103 {
104   static char tagbuf[5] = "n-??";
105
106   while (n && *p == '0') {
107     n--;
108     p++;
109   }
110   if (!n)
111     return (0);
112
113   if (f & f_and)
114     au_play("n-and");
115   if (n == 1)
116     digit(*p);
117   else if (*p == '1') {
118     tagbuf[2] = p[0];
119     tagbuf[3] = p[1];
120     au_play(tagbuf);
121   } else {
122     tagbuf[2] = *p++;
123     tagbuf[3] = '0';
124     au_play(tagbuf);
125     if (*p != '0')
126       digit(*p);
127   }
128   return (1);
129 }
130
131 /* --- @bignum@ --- *
132  *
133  * Arguments:   @const char *p@ = pointer to digits
134  *              @size_t n@ = number of digits
135  *
136  * Returns:     Nonzero if the number was nonzero.
137  *
138  * Use:         Reads out a (large) integer in English.
139  */
140
141 static int bignum(const char *p, size_t n)
142 {
143   int nz = 0;
144   int rc;
145
146   if (n > 6) {
147     digits(p, n);
148     return (1);
149   }
150   if (n > 3) {
151     rc = bignum(p, n - 3);
152     p += n - 3;
153     n = 3;
154     if (rc) {
155       au_play("n-thou");
156       nz = 1;
157     }
158   }
159   if (n > 2) {
160     if (*p == '0') {
161       p++;
162     } else {
163       digit(*p++);
164       au_play("n-hun");
165       nz = 1;
166     }
167     n--;
168   }
169   return (lasttwo(p, n, nz ? f_and : 0) || nz);
170 }
171
172 /* --- @aunum@ --- *
173  *
174  * Arguments:   @const char *p@ = pointer to number's textual representation
175  *
176  * Returns:     ---
177  *
178  * Use:         Reads the given number aloud.
179  */
180
181 void aunum(const char *p)
182 {
183   size_t pl;
184   int nz;
185
186   /* --- Pick off a leading sign --- */
187
188 again:
189   if (*p == '+')
190     p++;
191   else if (*p == '-') {
192     au_play("n-minus");
193     p++;
194   }
195
196   /* --- Work out how many digits we have --- */
197
198   p += strspn(p, "0");
199   pl = strspn(p, "0123456789");
200   nz = bignum(p, pl);
201   p += pl;
202
203   /* --- If the value was zero, and there's no `point', say `zero' --- */
204
205   if (*p != '.' && !nz)
206     au_play("n-0");
207   if (*p == '.') {
208     au_play("n-point");
209     p++;
210     pl = strspn(p, "0123456789");
211     digits(p, pl);
212     p += pl;
213   }
214   if (*p == 'e' || *p == 'E') {
215     au_play("n-exp");
216     p++;
217     goto again;
218   }
219
220   /* --- Run out of things to do --- */
221
222   return;
223 }
224
225 /* --- @aunum_ulong@ --- *
226  *
227  * Arguments:   @unsigned long n@ = number to be read
228  *
229  * Returns:     ---
230  *
231  * Use:         Reads a number expressed as an @unsigned long@.
232  */
233
234 void aunum_ulong(unsigned long n)
235 {
236   dstr d = DSTR_INIT;
237
238   dstr_putf(&d, "%lu", n);
239   aunum(d.buf);
240   dstr_destroy(&d);
241 }
242
243 /*----- That's all, folks -------------------------------------------------*/