@@ -124,94 +124,7 @@ 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-
189- // Command parsing with line handling
190- bool ATCmdParser::vsend (const char *command, std::va_list args)
191- {
192- // Create and send command
193- if (vsprintf (_buffer, command, args) < 0 ) {
194- return false ;
195- }
196-
197- for (int i = 0 ; _buffer[i]; i++) {
198- if (putc (_buffer[i]) < 0 ) {
199- return false ;
200- }
201- }
202-
203- // Finish with newline
204- for (size_t i = 0 ; _output_delimiter[i]; i++) {
205- if (putc (_output_delimiter[i]) < 0 ) {
206- return false ;
207- }
208- }
209-
210- debug_if (_dbg_on, " AT> %s\n " , _buffer);
211- return true ;
212- }
213-
214- bool ATCmdParser::vrecv (const char *response, std::va_list args)
127+ int ATCmdParser::vrecvscanf (const char *response, std::va_list args, bool issacnf)
215128{
216129restart:
217130 _aborted = false ;
@@ -259,20 +172,27 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
259172 int j = 0 ;
260173
261174 while (true ) {
175+ // Ran out of space
176+ if (j + 1 >= _buffer_size - offset) {
177+ return -1 ;
178+ }
179+
262180 // If just peeking for OOBs, and at start of line, check
263181 // readability
264- if (!response && j == 0 && !_fh->readable ()) {
265- return false ;
182+ if (!issacnf && ! response && j == 0 && !_fh->readable ()) {
183+ return - 1 ;
266184 }
185+
267186 // Receive next character
268187 int c = getc ();
269188 if (c < 0 ) {
270189 debug_if (_dbg_on, " AT(Timeout)\n " );
271- return false ;
190+ return - 1 ;
272191 }
192+
273193 // Simplify newlines (borrowed from retarget.cpp)
274194 if ((c == CR && _in_prev != LF) ||
275- (c == LF && _in_prev != CR)) {
195+ (c == LF && _in_prev != CR)) {
276196 _in_prev = c;
277197 c = ' \n ' ;
278198 } else if ((c == CR && _in_prev == LF) ||
@@ -283,24 +203,27 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
283203 } else {
284204 _in_prev = c;
285205 }
206+
286207 _buffer[offset + j++] = c;
287208 _buffer[offset + j] = 0 ;
288209
289210 // 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 ;
211+ if (!issacnf) {
212+ for (struct oob *oob = _oobs; oob; oob = oob->next ) {
213+ if ((unsigned )j == oob->len && memcmp (
214+ oob->prefix , _buffer + offset, oob->len ) == 0 ) {
215+ debug_if (_dbg_on, " AT! %s\n " , oob->prefix );
216+ _oob_cb_count++;
217+ oob->cb ();
218+
219+ if (_aborted) {
220+ debug_if (_dbg_on, " AT(Aborted)\n " );
221+ return false ;
222+ }
223+ // oob may have corrupted non-reentrant buffer,
224+ // so we need to set it up again
225+ goto restart;
300226 }
301- // oob may have corrupted non-reentrant buffer,
302- // so we need to set it up again
303- goto restart;
304227 }
305228 }
306229
@@ -323,6 +246,10 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
323246 // Store the found results
324247 vsscanf (_buffer + offset, _buffer, args);
325248
249+ if (issacnf) {
250+ return j;
251+ }
252+
326253 // Jump to next line and continue parsing
327254 response += i;
328255 break ;
@@ -337,6 +264,31 @@ bool ATCmdParser::vrecv(const char *response, std::va_list args)
337264 }
338265 }
339266
267+ return 1 ;
268+ }
269+
270+ // Command parsing with line handling
271+ bool ATCmdParser::vsend (const char *command, std::va_list args)
272+ {
273+ // Create and send command
274+ if (vsprintf (_buffer, command, args) < 0 ) {
275+ return false ;
276+ }
277+
278+ for (int i = 0 ; _buffer[i]; i++) {
279+ if (putc (_buffer[i]) < 0 ) {
280+ return false ;
281+ }
282+ }
283+
284+ // Finish with newline
285+ for (size_t i = 0 ; _output_delimiter[i]; i++) {
286+ if (putc (_output_delimiter[i]) < 0 ) {
287+ return false ;
288+ }
289+ }
290+
291+ debug_if (_dbg_on, " AT> %s\n " , _buffer);
340292 return true ;
341293}
342294
@@ -354,7 +306,7 @@ int ATCmdParser::scanf(const char *format, ...)
354306{
355307 std::va_list args;
356308 va_start (args, format);
357- int res = vscanf (format, args);
309+ int res = vrecvscanf (format, args, true );
358310 va_end (args);
359311 return res;
360312}
@@ -372,9 +324,9 @@ bool ATCmdParser::recv(const char *response, ...)
372324{
373325 std::va_list args;
374326 va_start (args, response);
375- bool res = vrecv (response, args);
327+ int res = vrecvscanf (response, args, false );
376328 va_end (args);
377- return res;
329+ return ( res > 0 ) ? true : false ;
378330}
379331
380332// oob registration
0 commit comments