chiark / gitweb /
Initial revision
[jog] / serial.c
1 /* -*-c-*-
2  *
3  * $Id: serial.c,v 1.1 2002/01/25 19:34:45 mdw Exp $
4  *
5  * Common serial functionality
6  *
7  * (c) 2001 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: serial.c,v $
32  * Revision 1.1  2002/01/25 19:34:45  mdw
33  * Initial revision
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <ctype.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #include "serial.h"
44
45 /*----- Main code ---------------------------------------------------------*/
46
47 /* --- @getbaud@ --- *
48  *
49  * Arguments:   @const char *p@ = pointer to string
50  *              @const char **pp@ = where to store final pointer
51  *
52  * Returns:     Baud rate, or @-1@ on failure.
53  *
54  * Use:         Parses a baud rate, either as a raw number or as an
55  *              expression like `9k6'.
56  */
57
58 static long getbaud(const char *p, const char **pp)
59 {
60   long x = 0;
61   long f = 1, s = 10;
62   int ok = 0;
63
64   /* --- Main loop --- */
65
66   for (;;) {
67     int ch = (unsigned char)*p;
68
69     switch (ch) {
70       case 'k':
71       case 'K':
72         f = 1000;
73         goto factor;
74       case 'm':
75       case 'M':
76         f = 1000000;
77         goto factor;
78       factor:
79         if (ok != 1)
80           return (-1);
81         x *= f;
82         s = 1;
83         ok = 2;
84         break;
85       default:
86         if (!isdigit(ch))
87           goto done;
88         if (!ok)
89           ok = 1;
90         if (ok == 2) {
91           if (f == 1)
92             return (-1);
93           f /= 10;
94         }
95         x = x * s + (ch - '0') * f;
96         break;
97     }
98     p++;
99   }
100 done:
101   if (!ok)
102     return (-1);
103   if (pp)
104     *pp = p;
105   return (x);
106 }
107
108 /* --- @serial_parse@ --- *
109  *
110  * Arguments:   @const char *p@ = configuration string to parse
111  *              @serial_config *sc@ = pointer to serial config structure
112  *
113  * Returns:     Zero if OK, or @-1@ on error.
114  *
115  * Use:         Parses a serial config string into something more
116  *              reasonable.  The config structure should have been
117  *              initialized to something sensible (e.g., @SERIAL_INIT@)
118  *              already.
119  */
120
121 int serial_parse(const char *p, serial_config *sc)
122 {
123   long x;
124   const char *q;
125   char *qq;
126
127   /* --- Pick out an initial baud rate --- */
128
129   while (isspace((unsigned char)*p))
130     p++;
131   if (*p != 0 && *p != ':') {
132     if ((x = getbaud(p, &p)) < 0)
133       goto fail;
134     sc->baud = x;
135   }
136   while (isspace((unsigned char)*p))
137     p++;
138   if (*p == ':')
139     p++;
140
141   /* --- Pick out a word length --- */
142
143   while (isspace((unsigned char)*p))
144     p++;
145   if ((x = strtol(p, &qq, 10)) == 0)
146     goto fail;
147   p = qq;
148   sc->wordlen = x;
149   while (isspace((unsigned char)*p))
150     p++;
151   if (*p == '-')
152     p++;
153
154   /* --- Pick out a parity designation --- */
155
156   while (isspace((unsigned char)*p))
157     p++;
158   for (q = p; isalpha((unsigned char)*q); q++)
159     ;
160   if (q == p)
161     goto fail;
162   if (strncmp(p, "none", q - p) == 0)
163     sc->parity = PARITY_NONE;
164   else if (strncmp(p, "odd", q - p) == 0)
165     sc->parity = PARITY_ODD;
166   else if (strncmp(p, "even", q - p) == 0)
167     sc->parity = PARITY_EVEN;
168   else
169     goto fail;
170   p = q;
171   while (isspace((unsigned char)*p))
172     p++;
173   if (*p == '-')
174     p++;
175
176   /* --- Pick out a number of stop bits --- */
177
178   while (isspace((unsigned char)*p))
179     p++;
180   if ((x = strtol(p, &qq, 10)) == 0)
181     goto fail;
182   p = qq;
183   sc->stopbits = x;
184   while (isspace((unsigned char)*p))
185     p++;
186
187   /* --- Done --- */
188
189   if (*p)
190     goto fail;
191   return (0);
192
193 fail:
194   return (-1);
195 }
196
197 /*----- Test rig ----------------------------------------------------------*/
198
199 #ifdef TEST_RIG
200
201 #include <stdio.h>
202
203 int main(int argc, char *argv[])
204 {
205   int i;
206   static const char *ptab[] = { "none", "odd", "even" };
207
208   for (i = 1; i < argc; i++) {
209     serial_config sc = SERIAL_INIT;
210
211     if (serial_parse(argv[i], &sc))
212       printf("invalid serial configuration `%s'\n", argv[i]);
213     else {
214       printf("%lu %u-%s-%u\n", sc.baud, sc.wordlen,
215              ptab[sc.parity], sc.stopbits);
216     }
217   }
218   return (0);
219 }
220
221 #endif
222
223 /*----- That's all, folks -------------------------------------------------*/