@@ -124,68 +124,6 @@ int ATCmdParser::vprintf(const char *format, std::va_list args)
124124 return i;
125125}
126126
127- int ATCmdParser::vscanf (const char *format, std::va_list args)
128- {
129- // Since format is const, we need to copy it into our buffer to
130- // add the line's null terminator and clobber value-matches with asterisks.
131- //
132- // We just use the beginning of the buffer to avoid unnecessary allocations.
133- int i = 0 ;
134- int offset = 0 ;
135-
136- while (format[i]) {
137- if (format[i] == ' %' && format[i + 1 ] != ' %' && format[i + 1 ] != ' *' ) {
138- _buffer[offset++] = ' %' ;
139- _buffer[offset++] = ' *' ;
140- i++;
141- } else {
142- _buffer[offset++] = format[i++];
143- }
144- }
145-
146- // Scanf has very poor support for catching errors
147- // fortunately, we can abuse the %n specifier to determine
148- // if the entire string was matched.
149- _buffer[offset++] = ' %' ;
150- _buffer[offset++] = ' n' ;
151- _buffer[offset++] = 0 ;
152-
153- // To workaround scanf's lack of error reporting, we actually
154- // make two passes. One checks the validity with the modified
155- // format string that only stores the matched characters (%n).
156- // The other reads in the actual matched values.
157- //
158- // We keep trying the match until we succeed or some other error
159- // derails us.
160- int j = 0 ;
161-
162- while (true ) {
163- // Ran out of space
164- if (j + 1 >= _buffer_size - offset) {
165- return false ;
166- }
167- // Receive next character
168- int c = getc ();
169- if (c < 0 ) {
170- return -1 ;
171- }
172- _buffer[offset + j++] = c;
173- _buffer[offset + j] = 0 ;
174-
175- // Check for match
176- int count = -1 ;
177- sscanf (_buffer + offset, _buffer, &count);
178-
179- // We only succeed if all characters in the response are matched
180- if (count == j) {
181- // Store the found results
182- vsscanf (_buffer + offset, format, args);
183- return j;
184- }
185- }
186- }
187-
188-
189127// Command parsing with line handling
190128bool ATCmdParser::vsend (const char *command, std::va_list args)
191129{
@@ -211,7 +149,7 @@ bool ATCmdParser::vsend(const char *command, std::va_list args)
211149 return true ;
212150}
213151
214- bool ATCmdParser::vrecv (const char *response, std::va_list args)
152+ int ATCmdParser::vrecvscanf (const char *response, std::va_list args, bool multiline )
215153{
216154restart:
217155 _aborted = false ;
@@ -259,17 +197,24 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
259197 int j = 0 ;
260198
261199 while (true ) {
200+ // Ran out of space
201+ if (j + 1 >= _buffer_size - offset) {
202+ return -1 ;
203+ }
204+
262205 // If just peeking for OOBs, and at start of line, check
263206 // readability
264207 if (!response && j == 0 && !_fh->readable ()) {
265- return false ;
208+ return - 1 ;
266209 }
210+
267211 // Receive next character
268212 int c = getc ();
269213 if (c < 0 ) {
270214 debug_if (_dbg_on, " AT(Timeout)\n " );
271- return false ;
215+ return - 1 ;
272216 }
217+
273218 // Simplify newlines (borrowed from retarget.cpp)
274219 if ((c == CR && _in_prev != LF) ||
275220 (c == LF && _in_prev != CR)) {
@@ -283,24 +228,27 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
283228 } else {
284229 _in_prev = c;
285230 }
231+
286232 _buffer[offset + j++] = c;
287233 _buffer[offset + j] = 0 ;
288234
289235 // Check for oob data
290- for (struct oob *oob = _oobs; oob; oob = oob->next ) {
291- if ((unsigned )j == oob->len && memcmp (
292- oob->prefix , _buffer + offset, oob->len ) == 0 ) {
293- debug_if (_dbg_on, " AT! %s\n " , oob->prefix );
294- _oob_cb_count++;
295- oob->cb ();
296-
297- if (_aborted) {
298- debug_if (_dbg_on, " AT(Aborted)\n " );
299- return false ;
236+ if (multiline) {
237+ for (struct oob *oob = _oobs; oob; oob = oob->next ) {
238+ if ((unsigned )j == oob->len && memcmp (
239+ oob->prefix , _buffer + offset, oob->len ) == 0 ) {
240+ debug_if (_dbg_on, " AT! %s\n " , oob->prefix );
241+ _oob_cb_count++;
242+ oob->cb ();
243+
244+ if (_aborted) {
245+ debug_if (_dbg_on, " AT(Aborted)\n " );
246+ return false ;
247+ }
248+ // oob may have corrupted non-reentrant buffer,
249+ // so we need to set it up again
250+ goto restart;
300251 }
301- // oob may have corrupted non-reentrant buffer,
302- // so we need to set it up again
303- goto restart;
304252 }
305253 }
306254
@@ -323,6 +271,10 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
323271 // Store the found results
324272 vsscanf (_buffer + offset, _buffer, args);
325273
274+ if (!multiline) {
275+ return j;
276+ }
277+
326278 // Jump to next line and continue parsing
327279 response += i;
328280 break ;
@@ -337,7 +289,17 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
337289 }
338290 }
339291
340- return true ;
292+ return 1 ;
293+ }
294+
295+ int ATCmdParser::vscanf (const char *format, std::va_list args)
296+ {
297+ return vrecvscanf (format, args, false );
298+ }
299+
300+ bool ATCmdParser::vrecv (const char *response, std::va_list args)
301+ {
302+ return (vrecvscanf (response, args, true )) > 0 ? true : false ;
341303}
342304
343305// Mapping to vararg functions
@@ -354,7 +316,7 @@ int ATCmdParser::scanf(const char *format, ...)
354316{
355317 std::va_list args;
356318 va_start (args, format);
357- int res = vscanf (format, args);
319+ int res = vrecvscanf (format, args, false );
358320 va_end (args);
359321 return res;
360322}
@@ -372,9 +334,9 @@ bool ATCmdParser::recv(const char *response, ...)
372334{
373335 std::va_list args;
374336 va_start (args, response);
375- bool res = vrecv (response, args);
337+ int res = vrecvscanf (response, args, true );
376338 va_end (args);
377- return res;
339+ return ( res > 0 ) ? true : false ;
378340}
379341
380342// oob registration
0 commit comments