HP85 GPIB Disk Emulator  1.0
HP85GPIBDiskEmulator
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
sscanf.c
Go to the documentation of this file.
1 // =============================================
2 // Copyright � 2003 - 2016 Mike Gore, Waterloo, ON N2L 5N4, Canada
3 //
4 // Permission is hereby granted to use this Software for any purpose
5 // including combining with commercial products, creating derivative
6 // works, and redistribution of source or binary code, without
7 // limitation or consideration. Any redistributed copies of this
8 // Software must include the above Copyright Notice.
9 //
10 // THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR MAKES NO
11 // WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS
12 // SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
13 // =============================================
14 // History
15 // Written: 2 April 2003 Mike Gore <magore@icr1.uwater.loo.ca>
16 // April 2 - April 8th extesive edits
17 // April 8 Alpha Release
18 // 12 Oct 2016
19 // =============================================
20 // =============================================
21 // Note:!!!!
22 // Use TAB STOPS to 4 or this document will look wrong
23 // =============================================
24 
25 #include "user_config.h"
26 
27 #include <stdint.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <math.h>
31 
32 #include "mathio.h"
33 
34 #ifdef SMALL_SSCANF
35 
36 // =============================================
37 //
38 //
39 // WRITTEN by MIKE GORE JUN 1999
40 //
41 // SCANF without multiplies!
42 // Work in progress
43 
44 int sscanf(const char *strp, const char *fmt, ...)
45 {
46  va_list ap;
47  int SIGN = 0;
48  uint8_t SIZE;
49  int args = 0; // Arguments
50  uint8_t width;
51  uint8_t base;
52  uint8_t shift;
53  uint8_t ch;
54  uint8_t spec;
55  unsigned long num;
56 
57  va_start(ap,fmt);
58 
59  while ( (spec = *fmt++) )
60  {
61 
62 // FIXME match all non format spec components with input string HERE
63 // - Of course the format spec includes the width spec, etc
64 // - For now we discard any non % qualified format characters
65 // up to the % character and then the rest of the code eats whats
66 // left in processing the spec later on. In other words we KNOW that
67 // all characters up to a % are unused in the spec itself but really
68 // should be matched with the input to be correct - othersise could cause
69 // parse errors - if present. For now we skip spaces and commas
70 // to avoid the most common issues
71 //
72 
73 //
74 // Skip non format characters - for now
75  if (spec != '%')
76  {
77  if(spec == *strp)
78  ++strp;
79  continue;
80  }
81 
82 // we had a '%'
83  spec = *fmt;
84 
85 // Sync up input string to current argument we want in format spec
86 // Skip white space and commas in input string - for now KLUDGE
87 //
88  while ( (ch = *strp) )
89  {
90  if(ch == '\t' || ch == ' ' || ch == ',')
91  {
92  ++strp;
93  continue;
94  }
95  break;
96  }
97 
98  width = 0; // Init width
99 
100  while( (spec = *fmt) ) // spec and fmt point past %
101  {
102  if(!(spec >= '0' && spec <= '9'))
103  break;
104  base = width; // width *= 10, base is just a temp here
105  width <<=2;
106  width += base;
107  width <<=1;
108 
109  width += (spec - '0');
110  ++fmt;
111  }
112 
113 // Init numeric control flags in case we have a number to process
114 
115  SIZE = sizeof(int); // Long/Short/Tiny flag, int is default
116  base = 0; // If base gets set below we have a number!
117  shift = 0; // Used for fast multiply
118 
119 // Handle LARGE numbers
120 //
121 
122  if (spec == 'l') // Large
123  {
124  SIZE = sizeof(long);
125  spec = *fmt++;
126  }
127  if (spec == 't') // tiny
128  {
129  SIZE = sizeof(char);
130  spec = *fmt++;
131  }
132 
133 // spec has our format specifier!
134  switch (spec)
135  {
136  case '%':
137  break;
138  case 'c':
139  {
140  unsigned char *c;
141  c = va_arg(ap,unsigned char *);
142  *c = *strp;
143  ++strp;
144  }
145  break;
146  case 's':
147  {
148  unsigned char *p;
149  unsigned char c;
150  p = va_arg(ap,unsigned char *);
151  while (width)
152  {
153  c = *strp;
154  if (!c || c == ' ' || c == '\t')
155  break;
156  *p = c;
157  ++p;
158  ++strp;
159  --width;
160  }
161  *p = 0;
162  }
163  break;
164  case 'B':
165  SIZE = sizeof(long);
166  case 'b':
167  base = 2;
168  shift = 1;
169  break;
170  case 'O':
171  SIZE = sizeof(long);
172  case 'o':
173  base = 8;
174  shift = 3;
175  break;
176  case 'X':
177  SIZE = sizeof(long);
178  case 'x':
179  base = 16;
180  shift = 4;
181  break;
182  case 'U':
183  case 'D':
184  SIZE = sizeof(long);
185  case 'u':
186  case 'd':
187  base = 10;
188 //printf("sscanf: sizeof(long) = %d\n", sizeof(long));
189 //printf("sscanf: sizeof(int) = %d\n", sizeof(int));
190 //printf("sscanf: size = %d, base = %d\n", (int)SIZE, (int)base);
191 //printf("sscanf strp:%s\n", strp);
192  break;
193  case 'f':
194  SIZE = sizeof(double);
195  break;
196  default:
197  break;
198  }
199 // IF base is non zero we have some kind of number to process
200 
201  if(base)
202  {
203  num = 0;
204  SIGN = 0;
205  if (!width)
206  width = strlen(strp);
207 
208  ch = *strp;
209  if (ch == '-')
210  {
211  SIGN = 1;
212  ++strp;
213  }
214  else if(ch == '+')
215  {
216  ++strp;
217  }
218 
219  while (width && (ch = *strp))
220  {
221  if (ch < '0')
222  break;
223 
224  if (ch >= 'a')
225  ch -= ('a' - 10);
226  else if (ch >= 'A')
227  ch -= ('A' - 10);
228  else
229  ch -= '0';
230 
231  if (ch >= base)
232  break;
233 
234  if(base == 10)
235  {
236  unsigned long temp;
237  num <<= 1;
238  temp = num;
239  num <<= 2;
240  num += temp;
241  }
242  else
243  {
244  num <<= shift;
245  }
246  num += ch;
247  ++strp;
248  --width;
249 //printf("sscanf: %ld\n",num);
250  } // END WHILE
251  if(SIZE == sizeof(long))
252  {
253  unsigned long *c;
254  c = va_arg(ap,unsigned long *);
255  if(SIGN)
256  *c = (unsigned long) -num;
257  else
258  *c = (unsigned long) num;
259  }
260  else if(SIZE == sizeof(int))
261  {
262  unsigned int *c;
263  c = va_arg(ap,unsigned int *);
264  if(SIGN)
265  *c = (unsigned int) -num;
266  else
267  *c = (unsigned int) num;
268  }
269  else
270  {
271  unsigned char *c;
272  c = va_arg(ap,uint8_t *);
273  if(SIGN)
274  *c = (unsigned char) -num;
275  else
276  *c = (unsigned char) num;
277  }
278  } // END IF(base && width)
279  else if(SIZE = sizeof(double))
280  {
281 // FIXME width
282  double *d = va_arg(ap,double *);
283  char *ptr,*endp;
284  int len = strlen(strp);
285  if(!width)
286  width = len;
287  if(width > len)
288  width = len;
289  ptr = stralloc((char *)strp);
290  *d = strtod(ptr, &endp);
291  free(ptr);
292  strp += (endp - ptr);
293  }
294  ++args;
295  } // END WHILE
296  return (args);
297 }
298 #endif // ifdef SMALL_SSCANF
strtod
MEMSPACE double strtod(const char *nptr, char **endptr)
free
#define free(p)
Definition: user_config.h:126
stralloc
MEMSPACE char * stralloc(char *str)
Allocate space for string.
Definition: stringsup.c:406
strlen
MEMSPACE size_t WEAK_ATR strlen(const char *str)
String Length.
Definition: stringsup.c:144
sscanf
int sscanf(const char *strp, const char *fmt,...)
mathio.h
Math IO functions, and verious conversion code with floating point support.
_printf_t::len
int len
Definition: mathio.h:84