chiark / gitweb /
realtime: movpos: debug output: exclude some more stuff from the default movpos output
[trains.git] / hostside / parseutils.c
1 /*
2  * common
3  * utilities for helping parsing
4  */
5
6 #include <stdarg.h>
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "common.h"
12
13 int badcmd(ParseState *ps, const char *fmt, ...) {
14   int r;
15   va_list al;
16   va_start(al,fmt);
17   r= vbadcmd(ps,fmt,al);
18   va_end(al);
19   return r;
20 }
21
22 int ps_word(ParseState *ps) {
23   const char *space;
24   if (!ps->remain) { ps->lthisword=0; return -1; }
25   space= strchr(ps->remain, ' ');
26   ps->thisword= ps->remain;
27   if (space) {
28     ps->lthisword= space - ps->thisword;
29     ps->remain= space + 1;
30   } else {
31     ps->lthisword= strlen(ps->remain);
32     ps->remain= 0;
33   }
34   return 0;
35 }
36
37 int ps_needword(ParseState *ps) {
38   if (ps_word(ps)<0) return badcmd(ps,"too few args");
39   return 0;
40 }
41
42 void ps_pushbackword(ParseState *ps) {
43   ps->remain= ps->thisword;
44 }
45
46 int ps_neednumber(ParseState *ps, long *r,
47                         long mi, long mx, const char *wh) {
48   char *ep;
49   long v;
50   
51   MUSTECR( ps_needword(ps) );
52   errno= 0; v= strtol(ps->thisword,&ep,0);
53   if (errno || ep != ps->thisword + ps->lthisword)
54     return badcmd(ps,"invalid number for %s",wh);
55   if (v < mi || v > mx)
56     return badcmd(ps,"%s %ld out of range %ld..%ld",wh,v,mi,mx);
57   *r= v;
58   return 0;
59 }
60
61 int ps_neednoargs(ParseState *ps) {
62   if (ps->remain)
63     return badcmd(ps,"too many arguments");
64   return 0;
65 }
66  
67 int ps_needhextoend(ParseState *ps, Byte *d, int *len_io) {
68   Byte *d_begin, *d_end;
69   char buf[3], *ep;
70
71   d_begin= d;
72   d_end= d + *len_io;
73   buf[2]= 0;
74   
75   if (!ps->remain) return badcmd(ps,"need hex data block");
76   for (;;) {
77     if (ps_word(ps)<0) break;
78     while (ps->lthisword > 0) {
79       if (ps->lthisword & 1)
80         return badcmd(ps,"hex data block with odd number of digits in part");
81       buf[0]= ps->thisword[0];
82       buf[1]= ps->thisword[1];
83       if (d >= d_end) return badcmd(ps,"hex data block too long");
84       *d++= strtoul(buf,&ep,16);
85       if (*ep) return badcmd(ps,"invalid digit in hex data block");
86       ps->lthisword -= 2;
87       ps->thisword += 2;
88     }
89   }
90
91   *len_io= d - d_begin;
92   return 0;
93 }
94
95 const void *any_lookup(ParseState *ps, const void *inf, int ninfsmax,
96                        size_t sz) {
97   const char *tname;
98   int i;
99   
100   for (i=0;
101        i<ninfsmax && (tname= *(const char *const*)inf);
102        i++, inf= (const char*)inf + sz)
103     if (!thiswordstrcmp(ps,tname))
104       return inf;
105   return 0;
106 }
107
108 const void *any_needword_lookup(ParseState *ps, const void *infs, int ninfsmax,
109                                 size_t sz, const char *what) {
110   int ec;
111   const void *r;
112
113   ec= ps_needword(ps);  if (ec) return 0;
114   r= any_lookup(ps,infs,ninfsmax,sz);
115   if (!r) {
116     badcmd(ps,"unknown %s %.*s",what, ps->lthisword,ps->thisword);
117     return 0;
118   }
119   return r;
120 }
121
122 int lstrstrcmp(const char *a, int la, const char *b) {
123   int lb, minl, r;
124
125   lb= strlen(b);
126   minl= la < lb ? la : lb;
127   r= memcmp(a,b,minl);
128   if (r) return r;
129
130   return (la < lb ? -1 :
131           la > lb ? 1 : 0);
132 }
133
134 int thiswordstrcmp(ParseState *ps, const char *b) {
135   return lstrstrcmp(ps->thisword, ps->lthisword, b);
136 }
137