Contiki-NG
Loading...
Searching...
No Matches
strformat.c
1/*
2 * Copyright (c) 2009, Simon Berg
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31/*---------------------------------------------------------------------------*/
32#include "contiki.h"
33
34#include <string.h>
35#include <strformat.h>
36/*---------------------------------------------------------------------------*/
37#define HAVE_DOUBLE
38#define HAVE_LONGLONG
39
40#ifndef LARGEST_SIGNED
41#ifdef HAVE_LONGLONG
42#define LARGEST_SIGNED long long int
43#else
44#define LARGEST_SIGNED long int
45#endif /* HAVE_LONGLONG */
46#endif /* LARGEST_SIGNED */
47
48#ifndef LARGEST_UNSIGNED
49#ifdef HAVE_LONGLONG
50#define LARGEST_UNSIGNED unsigned long long int
51#else
52#define LARGEST_UNSIGNED unsigned long int
53#endif /* HAVE_LONGLONG */
54#endif /* LARGEST_UNSIGNED */
55
56#ifndef POINTER_INT
57#define POINTER_INT uintptr_t
58#endif
59/*---------------------------------------------------------------------------*/
60typedef uint32_t FormatFlags;
61/*---------------------------------------------------------------------------*/
62#define MAKE_MASK(shift, size) (((1 << size) - 1) << (shift))
63/*---------------------------------------------------------------------------*/
64#define JUSTIFY_SHIFT 0
65#define JUSTIFY_SIZE 1
66#define JUSTIFY_RIGHT 0x0000
67#define JUSTIFY_LEFT 0x0001
68#define JUSTIFY_MASK MAKE_MASK(JUSTIFY_SHIFT, JUSTIFY_SIZE)
69/*---------------------------------------------------------------------------*/
70/* How a positive number is prefixed */
71#define POSITIVE_SHIFT (JUSTIFY_SHIFT + JUSTIFY_SIZE)
72#define POSITIVE_NONE (0x0000 << POSITIVE_SHIFT)
73#define POSITIVE_SPACE (0x0001 << POSITIVE_SHIFT)
74#define POSITIVE_PLUS (0x0003 << POSITIVE_SHIFT)
75#define POSITIVE_MASK MAKE_MASK(POSITIVE_SHIFT, POSITIVE_SIZE)
76
77#define POSITIVE_SIZE 2
78/*---------------------------------------------------------------------------*/
79#define ALTERNATE_FORM_SHIFT (POSITIVE_SHIFT + POSITIVE_SIZE)
80#define ALTERNATE_FORM_SIZE 1
81#define ALTERNATE_FORM (0x0001 << ALTERNATE_FORM_SHIFT)
82/*---------------------------------------------------------------------------*/
83#define PAD_SHIFT (ALTERNATE_FORM_SHIFT + ALTERNATE_FORM_SIZE)
84#define PAD_SIZE 1
85#define PAD_SPACE (0x0000 << PAD_SHIFT)
86#define PAD_ZERO (0x0001 << PAD_SHIFT)
87/*---------------------------------------------------------------------------*/
88#define SIZE_SHIFT (PAD_SHIFT + PAD_SIZE)
89#define SIZE_SIZE 3
90#define SIZE_CHAR (0x0001 << SIZE_SHIFT)
91#define SIZE_SHORT (0x0002 << SIZE_SHIFT)
92#define SIZE_INT (0x0000 << SIZE_SHIFT)
93#define SIZE_LONG (0x0003 << SIZE_SHIFT)
94#define SIZE_LONGLONG (0x0004 << SIZE_SHIFT)
95#define SIZE_MASK MAKE_MASK(SIZE_SHIFT, SIZE_SIZE)
96/*---------------------------------------------------------------------------*/
97#define CONV_SHIFT (SIZE_SHIFT + SIZE_SIZE)
98#define CONV_SIZE 3
99#define CONV_INTEGER (0x0001 << CONV_SHIFT)
100#define CONV_FLOAT (0x0002 << CONV_SHIFT)
101#define CONV_POINTER (0x0003 << CONV_SHIFT)
102#define CONV_STRING (0x0004 << CONV_SHIFT)
103#define CONV_CHAR (0x0005 << CONV_SHIFT)
104#define CONV_PERCENT (0x0006 << CONV_SHIFT)
105#define CONV_WRITTEN (0x0007 << CONV_SHIFT)
106#define CONV_MASK MAKE_MASK(CONV_SHIFT, CONV_SIZE)
107/*---------------------------------------------------------------------------*/
108#define RADIX_SHIFT (CONV_SHIFT + CONV_SIZE)
109#define RADIX_SIZE 2
110#define RADIX_DECIMAL (0x0001 << RADIX_SHIFT)
111#define RADIX_OCTAL (0x0002 << RADIX_SHIFT)
112#define RADIX_HEX (0x0003 << RADIX_SHIFT)
113#define RADIX_MASK MAKE_MASK(RADIX_SHIFT, RADIX_SIZE)
114/*---------------------------------------------------------------------------*/
115#define SIGNED_SHIFT (RADIX_SHIFT + RADIX_SIZE)
116#define SIGNED_SIZE 1
117#define SIGNED_NO (0x0000 << SIGNED_SHIFT)
118#define SIGNED_YES (0x0001 << SIGNED_SHIFT)
119#define SIGNED_MASK MAKE_MASK(SIGNED_SHIFT, SIGNED_SIZE)
120/*---------------------------------------------------------------------------*/
121#define CAPS_SHIFT (SIGNED_SHIFT + SIGNED_SIZE)
122#define CAPS_SIZE 1
123#define CAPS_NO (0x0000 << CAPS_SHIFT)
124#define CAPS_YES (0x0001 << CAPS_SHIFT)
125#define CAPS_MASK MAKE_MASK(CAPS_SHIFT, CAPS_SIZE)
126/*---------------------------------------------------------------------------*/
127#define FLOAT_SHIFT (CAPS_SHIFT + CAPS_SIZE)
128#define FLOAT_SIZE 2
129#define FLOAT_NORMAL (((uint32_t)0x0000) << FLOAT_SHIFT)
130#define FLOAT_EXPONENT (((uint32_t)0x0001) << FLOAT_SHIFT)
131#define FLOAT_DEPENDANT (((uint32_t)0x0002) << FLOAT_SHIFT)
132#define FLOAT_HEX (((uint32_t)0x0003) << FLOAT_SHIFT)
133#define FLOAT_MASK MAKE_MASK(FLOAT_SHIFT, FLOAT_SIZE)
134/*---------------------------------------------------------------------------*/
135#define CHECKCB(res) { if((res) != STRFORMAT_OK) { return -1; } }
136/*---------------------------------------------------------------------------*/
137#define MAXCHARS_HEX ((sizeof(LARGEST_UNSIGNED) * 8) / 4)
138
139/* Largest number of characters needed for converting an unsigned integer. */
140#define MAXCHARS ((sizeof(LARGEST_UNSIGNED) * 8 + 2) / 3)
141/*---------------------------------------------------------------------------*/
142static FormatFlags
143parse_flags(const char **posp)
144{
145 FormatFlags flags = 0;
146 const char *pos = *posp;
147
148 while(1) {
149 switch(*pos) {
150 case '-':
151 flags |= JUSTIFY_LEFT;
152 break;
153 case '+':
154 flags |= POSITIVE_PLUS;
155 break;
156 case ' ':
157 flags |= POSITIVE_SPACE;
158 break;
159 case '#':
160 flags |= ALTERNATE_FORM;
161 break;
162 case '0':
163 flags |= PAD_ZERO;
164 break;
165 default:
166 *posp = pos;
167 return flags;
168 }
169
170 pos++;
171 }
172}
173/*---------------------------------------------------------------------------*/
174static unsigned int
175parse_uint(const char **posp)
176{
177 unsigned v = 0;
178 const char *pos = *posp;
179 char ch;
180
181 while((ch = *pos) >= '0' && ch <= '9') {
182 v = v * 10 + (ch - '0');
183 pos++;
184 }
185
186 *posp = pos;
187
188 return v;
189}
190/*---------------------------------------------------------------------------*/
191static unsigned int
192output_uint_decimal(char **posp, LARGEST_UNSIGNED v)
193{
194 unsigned int len;
195 char *pos = *posp;
196
197 while(v > 0) {
198 *--pos = (v % 10) + '0';
199 v /= 10;
200 }
201
202 len = *posp - pos;
203 *posp = pos;
204
205 return len;
206}
207/*---------------------------------------------------------------------------*/
208static unsigned int
209output_uint_hex(char **posp, LARGEST_UNSIGNED v, unsigned int flags)
210{
211 unsigned int len;
212 const char *hex = (flags & CAPS_YES) ? "0123456789ABCDEF" : "0123456789abcdef";
213 char *pos = *posp;
214
215 while(v > 0) {
216 *--pos = hex[(v % 16)];
217 v /= 16;
218 }
219
220 len = *posp - pos;
221 *posp = pos;
222
223 return len;
224}
225/*---------------------------------------------------------------------------*/
226static unsigned int
227output_uint_octal(char **posp, LARGEST_UNSIGNED v)
228{
229 unsigned int len;
230 char *pos = *posp;
231
232 while(v > 0) {
233 *--pos = (v % 8) + '0';
234 v /= 8;
235 }
236
237 len = *posp - pos;
238 *posp = pos;
239
240 return len;
241}
242/*---------------------------------------------------------------------------*/
243static strformat_result
244fill_space(const strformat_context_t *ctxt, unsigned int len)
245{
246 strformat_result res;
247 static const char buffer[16] = " ";
248
249 while(len > 16) {
250 res = ctxt->write_str(ctxt->user_data, buffer, 16);
251 if(res != STRFORMAT_OK) {
252 return res;
253 }
254 len -= 16;
255 }
256
257 if(len == 0) {
258 return STRFORMAT_OK;
259 }
260
261 return ctxt->write_str(ctxt->user_data, buffer, len);
262}
263/*---------------------------------------------------------------------------*/
264static strformat_result
265fill_zero(const strformat_context_t *ctxt, unsigned int len)
266{
267 strformat_result res;
268 static const char buffer[16] = "0000000000000000";
269
270 while(len > 16) {
271 res = ctxt->write_str(ctxt->user_data, buffer, 16);
272 if(res != STRFORMAT_OK) {
273 return res;
274 }
275 len -= 16;
276 }
277
278 if(len == 0) {
279 return STRFORMAT_OK;
280 }
281 return ctxt->write_str(ctxt->user_data, buffer, len);
282}
283/*---------------------------------------------------------------------------*/
284int
285format_str(const strformat_context_t *ctxt, const char *format, ...)
286{
287 int ret;
288 va_list ap;
289 va_start(ap, format);
290 ret = format_str_v(ctxt, format, ap);
291 va_end(ap);
292 return ret;
293}
294/*---------------------------------------------------------------------------*/
295int
296format_str_v(const strformat_context_t *ctxt, const char *format, va_list ap)
297{
298 unsigned int written = 0;
299 const char *pos = format;
300
301 while(*pos != '\0') {
302 FormatFlags flags;
303 unsigned int minwidth = 0;
304 int precision = -1; /* Negative means no precision */
305 char ch;
306 const char *start = pos;
307
308 while((ch = *pos) != '\0' && ch != '%') {
309 pos++;
310 }
311
312 if(pos != start) {
313 CHECKCB(ctxt->write_str(ctxt->user_data, start, pos - start));
314 written += pos - start;
315 }
316
317 if(*pos == '\0') {
318 return written;
319 }
320
321 pos++;
322
323 if(*pos == '\0') {
324 return written;
325 }
326
327 flags = parse_flags(&pos);
328
329 /* parse width */
330 if(*pos >= '1' && *pos <= '9') {
331 minwidth = parse_uint(&pos);
332 } else if(*pos == '*') {
333 int w = va_arg(ap, int);
334
335 if(w < 0) {
336 flags |= JUSTIFY_LEFT;
337 minwidth = -w;
338 } else {
339 minwidth = w;
340 }
341
342 pos++;
343 }
344
345 /* parse precision */
346 if(*pos == '.') {
347 pos++;
348
349 if(*pos >= '0' && *pos <= '9') {
350 precision = parse_uint(&pos);
351 } else if(*pos == '*') {
352 pos++;
353 precision = va_arg(ap, int);
354 if(precision < 0) {
355 precision = -1; /* Treat as if precision was omitted (C99) */
356 }
357 }
358 }
359
360 if(*pos == 'l') {
361 pos++;
362
363 if(*pos == 'l') {
364 flags |= SIZE_LONGLONG;
365 pos++;
366 } else {
367 flags |= SIZE_LONG;
368 }
369 } else if(*pos == 'h') {
370 pos++;
371
372 if(*pos == 'h') {
373 flags |= SIZE_CHAR;
374 pos++;
375 } else {
376 flags |= SIZE_SHORT;
377 }
378 } else if(*pos == 'z') {
379 if(sizeof(size_t) == sizeof(short)) {
380 flags |= SIZE_SHORT;
381 } else if(sizeof(size_t) == sizeof(long)) {
382 flags |= SIZE_LONG;
383#ifdef HAVE_LONGLONG
384 } else if(sizeof(size_t) == sizeof(long long)) {
385 flags |= SIZE_LONGLONG;
386 }
387#endif
388 pos++;
389 }
390
391 /* parse conversion specifier */
392 switch(*pos) {
393 case 'd':
394 case 'i':
395 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_YES;
396 break;
397 case 'u':
398 flags |= CONV_INTEGER | RADIX_DECIMAL | SIGNED_NO;
399 break;
400 case 'o':
401 flags |= CONV_INTEGER | RADIX_OCTAL | SIGNED_NO;
402 break;
403 case 'x':
404 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO;
405 break;
406 case 'X':
407 flags |= CONV_INTEGER | RADIX_HEX | SIGNED_NO | CAPS_YES;
408 break;
409#ifdef HAVE_DOUBLE
410 case 'f':
411 case 'F':
412 case 'e':
413 case 'E':
414 case 'g':
415 case 'G':
416 case 'a':
417 case 'A':
418 flags |= CONV_FLOAT;
419 break;
420#endif
421 case 'c':
422 flags |= CONV_CHAR;
423 break;
424 case 's':
425 flags |= CONV_STRING;
426 break;
427 case 'p':
428 flags |= CONV_POINTER;
429 break;
430 case 'n':
431 flags |= CONV_WRITTEN;
432 break;
433 case '%':
434 flags |= CONV_PERCENT;
435 break;
436 case '\0':
437 return written;
438 }
439 pos++;
440
441 switch(flags & CONV_MASK) {
442 case CONV_PERCENT:
443 CHECKCB(ctxt->write_str(ctxt->user_data, "%", 1));
444 written++;
445 break;
446 case CONV_INTEGER:
447 {
448 /* unsigned integers */
449 char *prefix = 0; /* sign, "0x" or "0X" */
450 unsigned int prefix_len = 0;
451 char buffer[MAXCHARS];
452 char *conv_pos = buffer + MAXCHARS;
453 unsigned int conv_len = 0;
454 unsigned int width = 0;
455 unsigned int precision_fill;
456 unsigned int field_fill;
457 LARGEST_UNSIGNED uvalue = 0;
458 int negative = 0;
459
460 if(precision < 0) {
461 precision = 1;
462 } else {
463 flags &= ~PAD_ZERO;
464 }
465
466 if(flags & SIGNED_YES) {
467 /* signed integers */
468 LARGEST_SIGNED value = 0;
469 switch(flags & SIZE_MASK) {
470 case SIZE_CHAR:
471 value = (signed char)va_arg(ap, int);
472 break;
473 case SIZE_SHORT:
474 value = (short)va_arg(ap, int);
475 break;
476 case SIZE_INT:
477 value = va_arg(ap, int);
478 break;
479#ifndef HAVE_LONGLONG
480 case SIZE_LONGLONG: /* Treat long long the same as long */
481#endif
482 case SIZE_LONG:
483 value = va_arg(ap, long);
484 break;
485#ifdef HAVE_LONGLONG
486 case SIZE_LONGLONG:
487 value = va_arg(ap, long long);
488 break;
489#endif
490 }
491 if(value < 0) {
492 uvalue = -value;
493 negative = 1;
494 } else {
495 uvalue = value;
496 }
497 } else {
498
499 switch(flags & SIZE_MASK) {
500 case SIZE_CHAR:
501 uvalue = (unsigned char)va_arg(ap, unsigned int);
502 break;
503 case SIZE_SHORT:
504 uvalue = (unsigned short)va_arg(ap, unsigned int);
505 break;
506 case SIZE_INT:
507 uvalue = va_arg(ap, unsigned int);
508 break;
509#ifndef HAVE_LONGLONG
510 case SIZE_LONGLONG: /* Treat long long the same as long */
511#endif
512 case SIZE_LONG:
513 uvalue = va_arg(ap, unsigned long);
514 break;
515#ifdef HAVE_LONGLONG
516 case SIZE_LONGLONG:
517 uvalue = va_arg(ap, unsigned long long);
518 break;
519#endif
520 }
521 }
522
523 switch(flags & (RADIX_MASK)) {
524 case RADIX_DECIMAL:
525 conv_len = output_uint_decimal(&conv_pos, uvalue);
526 break;
527 case RADIX_OCTAL:
528 conv_len = output_uint_octal(&conv_pos, uvalue);
529 break;
530 case RADIX_HEX:
531 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
532 break;
533 }
534
535 width += conv_len;
536 precision_fill = (precision > conv_len) ? precision - conv_len : 0;
537 if((flags & (RADIX_MASK | ALTERNATE_FORM))
538 == (RADIX_OCTAL | ALTERNATE_FORM)) {
539 if(precision_fill < 1) {
540 precision_fill = 1;
541 }
542 }
543
544 width += precision_fill;
545
546 if((flags & (RADIX_MASK | ALTERNATE_FORM))
547 == (RADIX_HEX | ALTERNATE_FORM) && uvalue != 0) {
548 prefix_len = 2;
549 if(flags & CAPS_YES) {
550 prefix = "0X";
551 } else {
552 prefix = "0x";
553 }
554 }
555
556 if(flags & SIGNED_YES) {
557 if(negative) {
558 prefix = "-";
559 prefix_len = 1;
560 } else {
561 switch(flags & POSITIVE_MASK) {
562 case POSITIVE_SPACE:
563 prefix = " ";
564 prefix_len = 1;
565 break;
566 case POSITIVE_PLUS:
567 prefix = "+";
568 prefix_len = 1;
569 break;
570 }
571 }
572 }
573
574 width += prefix_len;
575
576 field_fill = (minwidth > width) ? minwidth - width : 0;
577
578 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
579 if(flags & PAD_ZERO) {
580 precision_fill += field_fill;
581 field_fill = 0; /* Do not double count padding */
582 } else {
583 CHECKCB(fill_space(ctxt, field_fill));
584 }
585 }
586
587 if(prefix_len > 0) {
588 CHECKCB(ctxt->write_str(ctxt->user_data, prefix, prefix_len));
589 }
590 written += prefix_len;
591
592 CHECKCB(fill_zero(ctxt, precision_fill));
593 written += precision_fill;
594
595 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
596 written += conv_len;
597
598 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
599 CHECKCB(fill_space(ctxt, field_fill));
600 }
601 written += field_fill;
602 }
603 break;
604 case CONV_STRING:
605 {
606 unsigned int field_fill;
607 unsigned int len;
608 char *str = va_arg(ap, char *);
609
610 if(str) {
611 char *pos = str;
612 while(*pos != '\0') pos++;
613 len = pos - str;
614 } else {
615 str = "(null)";
616 len = 6;
617 }
618
619 if(precision >= 0 && precision < len) {
620 len = precision;
621 }
622
623 field_fill = (minwidth > len) ? minwidth - len : 0;
624
625 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
626 CHECKCB(fill_space(ctxt, field_fill));
627 }
628
629 CHECKCB(ctxt->write_str(ctxt->user_data, str, len));
630 written += len;
631
632 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
633 CHECKCB(fill_space(ctxt, field_fill));
634 }
635 written += field_fill;
636 }
637 break;
638 case CONV_POINTER:
639 {
640 LARGEST_UNSIGNED uvalue =
641 (LARGEST_UNSIGNED)(POINTER_INT)va_arg(ap, void *);
642 char buffer[MAXCHARS_HEX + 2];
643 char *conv_pos = buffer + MAXCHARS_HEX + 2;
644 unsigned int conv_len;
645 unsigned int field_fill;
646
647 conv_len = output_uint_hex(&conv_pos, uvalue, flags);
648
649 if(conv_len == 0) {
650 *--conv_pos = '0';
651 conv_len++;
652 }
653
654 *--conv_pos = 'x';
655 *--conv_pos = '0';
656 conv_len += 2;
657
658 field_fill = (minwidth > conv_len) ? minwidth - conv_len : 0;
659
660 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
661 CHECKCB(fill_space(ctxt, field_fill));
662 }
663
664 CHECKCB(ctxt->write_str(ctxt->user_data, conv_pos, conv_len));
665 written += conv_len;
666
667 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
668 CHECKCB(fill_space(ctxt, field_fill));
669 }
670
671 written += field_fill;
672 }
673 break;
674 case CONV_CHAR:
675 {
676 char ch = va_arg(ap, int);
677 unsigned int field_fill = (minwidth > 1) ? minwidth - 1 : 0;
678
679 if((flags & JUSTIFY_MASK) == JUSTIFY_RIGHT) {
680 CHECKCB(fill_space(ctxt, field_fill));
681 }
682
683 CHECKCB(ctxt->write_str(ctxt->user_data, &ch, 1));
684 written++;
685
686 if((flags & JUSTIFY_MASK) == JUSTIFY_LEFT) {
687 CHECKCB(fill_space(ctxt, field_fill));
688 }
689 written += field_fill;
690 }
691 break;
692 case CONV_WRITTEN:
693 /* %n is disabled for security reasons. Consume the pointer argument
694 to keep the va_list aligned for subsequent arguments, but never
695 write through it. */
696 (void)va_arg(ap, int *);
697 break;
698#ifdef HAVE_DOUBLE
699 case CONV_FLOAT:
700 /* Float formatting is not implemented, but consume the argument
701 to keep the va_list aligned for subsequent arguments. */
702 (void)va_arg(ap, double);
703 break;
704#endif
705 }
706 }
707
708 return written;
709}
710/*---------------------------------------------------------------------------*/
static volatile at86rf215_flags_t flags
The radio driver uses the following flags to keep track of the current state of the radio and IRQ eve...
Definition at86rf215.c:144
static int value(int type)
static void start(void)
Start measurement.