RTEMS CPU Kit with SuperCore  4.11.3
pgmspace.h
Go to the documentation of this file.
1 
40 /*
41  * Copyright (c) 2002 - 2007 Marek Michalkiewicz
42  * All rights reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions are met:
46  *
47  * * Redistributions of source code must retain the above copyright
48  * notice, this list of conditions and the following disclaimer.
49  *
50  * * Redistributions in binary form must reproduce the above copyright
51  * notice, this list of conditions and the following disclaimer in
52  * the documentation and/or other materials provided with the
53  * distribution.
54  *
55  * * Neither the name of the copyright holders nor the names of
56  * contributors may be used to endorse or promote products derived
57  * from this software without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
60  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
63  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69  * POSSIBILITY OF SUCH DAMAGE.
70  */
71 
72 #ifndef __PGMSPACE_H_
73 #define __PGMSPACE_H_ 1
74 
83 #define __need_size_t
84 #include <inttypes.h>
85 #include <stddef.h>
86 #include <avr/io.h>
87 
88 #ifndef __ATTR_CONST__
89 #define __ATTR_CONST__ __attribute__((__const__))
90 #endif
91 
92 #ifndef __ATTR_PROGMEM__
93 #define __ATTR_PROGMEM__ __attribute__((__progmem__))
94 #endif
95 
96 #ifndef __ATTR_PURE__
97 #define __ATTR_PURE__ __attribute__((__pure__))
98 #endif
99 
107 #define PROGMEM __ATTR_PROGMEM__
108 
109 #ifdef __cplusplus
110 extern "C" {
111 #endif
112 
113 #if defined(__DOXYGEN__)
114 /*
115  * Doxygen doesn't grok the appended attribute syntax of
116  * GCC, and confuses the typedefs with function decls, so
117  * supply a doxygen-friendly view.
118  */
127 typedef void PROGMEM prog_void;
134 typedef char PROGMEM prog_char;
135 
142 typedef unsigned char PROGMEM prog_uchar;
143 
144 
151 typedef int8_t PROGMEM prog_int8_t;
152 
159 typedef uint8_t PROGMEM prog_uint8_t;
160 
167 typedef int16_t PROGMEM prog_int16_t;
168 
175 typedef uint16_t PROGMEM prog_uint16_t;
176 
183 typedef int32_t PROGMEM prog_int32_t;
184 
191 typedef uint32_t PROGMEM prog_uint32_t;
192 
202 typedef int64_t PROGMEM prog_int64_t;
203 
213 typedef uint64_t PROGMEM prog_uint64_t;
214 #else /* !DOXYGEN */
215 typedef void prog_void PROGMEM;
216 typedef char prog_char PROGMEM;
217 typedef unsigned char prog_uchar PROGMEM;
218 
219 typedef int8_t prog_int8_t PROGMEM;
220 typedef uint8_t prog_uint8_t PROGMEM;
221 typedef int16_t prog_int16_t PROGMEM;
222 typedef uint16_t prog_uint16_t PROGMEM;
223 typedef int32_t prog_int32_t PROGMEM;
224 typedef uint32_t prog_uint32_t PROGMEM;
225 #if !__USING_MINT8
226 typedef int64_t prog_int64_t PROGMEM;
227 typedef uint64_t prog_uint64_t PROGMEM;
228 #endif
229 #endif /* defined(__DOXYGEN__) */
230 
231 /* Although in C, we can get away with just using __c, it does not work in
232  C++. We need to use &__c[0] to avoid the compiler puking. Dave Hylands
233  explaned it thusly,
234 
235  Let's suppose that we use PSTR("Test"). In this case, the type returned
236  by __c is a prog_char[5] and not a prog_char *. While these are
237  compatible, they aren't the same thing (especially in C++). The type
238  returned by &__c[0] is a prog_char *, which explains why it works
239  fine. */
240 
241 #if defined(__DOXYGEN__)
242 /*
243  * The #define below is just a dummy that serves documentation
244  * purposes only.
245  */
250 # define PSTR(s) ((const PROGMEM char *)(s))
251 #else /* !DOXYGEN */
252 /* The real thing. */
253 # define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];}))
254 #endif /* DOXYGEN */
255 
256 #define __LPM_classic__(addr) \
257 (__extension__({ \
258  uint16_t __addr16 = (uint16_t)(addr); \
259  uint8_t __result; \
260  __asm__ \
261  ( \
262  "lpm" "\n\t" \
263  "mov %0, r0" "\n\t" \
264  : "=r" (__result) \
265  : "z" (__addr16) \
266  : "r0" \
267  ); \
268  __result; \
269 }))
270 
271 #define __LPM_enhanced__(addr) \
272 (__extension__({ \
273  uint16_t __addr16 = (uint16_t)(addr); \
274  uint8_t __result; \
275  __asm__ \
276  ( \
277  "lpm %0, Z" "\n\t" \
278  : "=r" (__result) \
279  : "z" (__addr16) \
280  ); \
281  __result; \
282 }))
283 
284 #define __LPM_word_classic__(addr) \
285 (__extension__({ \
286  uint16_t __addr16 = (uint16_t)(addr); \
287  uint16_t __result; \
288  __asm__ \
289  ( \
290  "lpm" "\n\t" \
291  "mov %A0, r0" "\n\t" \
292  "adiw r30, 1" "\n\t" \
293  "lpm" "\n\t" \
294  "mov %B0, r0" "\n\t" \
295  : "=r" (__result), "=z" (__addr16) \
296  : "1" (__addr16) \
297  : "r0" \
298  ); \
299  __result; \
300 }))
301 
302 #define __LPM_word_enhanced__(addr) \
303 (__extension__({ \
304  uint16_t __addr16 = (uint16_t)(addr); \
305  uint16_t __result; \
306  __asm__ \
307  ( \
308  "lpm %A0, Z+" "\n\t" \
309  "lpm %B0, Z" "\n\t" \
310  : "=r" (__result), "=z" (__addr16) \
311  : "1" (__addr16) \
312  ); \
313  __result; \
314 }))
315 
316 #define __LPM_dword_classic__(addr) \
317 (__extension__({ \
318  uint16_t __addr16 = (uint16_t)(addr); \
319  uint32_t __result; \
320  __asm__ \
321  ( \
322  "lpm" "\n\t" \
323  "mov %A0, r0" "\n\t" \
324  "adiw r30, 1" "\n\t" \
325  "lpm" "\n\t" \
326  "mov %B0, r0" "\n\t" \
327  "adiw r30, 1" "\n\t" \
328  "lpm" "\n\t" \
329  "mov %C0, r0" "\n\t" \
330  "adiw r30, 1" "\n\t" \
331  "lpm" "\n\t" \
332  "mov %D0, r0" "\n\t" \
333  : "=r" (__result), "=z" (__addr16) \
334  : "1" (__addr16) \
335  : "r0" \
336  ); \
337  __result; \
338 }))
339 
340 #define __LPM_dword_enhanced__(addr) \
341 (__extension__({ \
342  uint16_t __addr16 = (uint16_t)(addr); \
343  uint32_t __result; \
344  __asm__ \
345  ( \
346  "lpm %A0, Z+" "\n\t" \
347  "lpm %B0, Z+" "\n\t" \
348  "lpm %C0, Z+" "\n\t" \
349  "lpm %D0, Z" "\n\t" \
350  : "=r" (__result), "=z" (__addr16) \
351  : "1" (__addr16) \
352  ); \
353  __result; \
354 }))
355 
356 #define __LPM_float_classic__(addr) \
357 (__extension__({ \
358  uint16_t __addr16 = (uint16_t)(addr); \
359  float __result; \
360  __asm__ \
361  ( \
362  "lpm" "\n\t" \
363  "mov %A0, r0" "\n\t" \
364  "adiw r30, 1" "\n\t" \
365  "lpm" "\n\t" \
366  "mov %B0, r0" "\n\t" \
367  "adiw r30, 1" "\n\t" \
368  "lpm" "\n\t" \
369  "mov %C0, r0" "\n\t" \
370  "adiw r30, 1" "\n\t" \
371  "lpm" "\n\t" \
372  "mov %D0, r0" "\n\t" \
373  : "=r" (__result), "=z" (__addr16) \
374  : "1" (__addr16) \
375  : "r0" \
376  ); \
377  __result; \
378 }))
379 
380 #define __LPM_float_enhanced__(addr) \
381 (__extension__({ \
382  uint16_t __addr16 = (uint16_t)(addr); \
383  float __result; \
384  __asm__ \
385  ( \
386  "lpm %A0, Z+" "\n\t" \
387  "lpm %B0, Z+" "\n\t" \
388  "lpm %C0, Z+" "\n\t" \
389  "lpm %D0, Z" "\n\t" \
390  : "=r" (__result), "=z" (__addr16) \
391  : "1" (__addr16) \
392  ); \
393  __result; \
394 }))
395 
396 #if defined (__AVR_HAVE_LPMX__)
397 #define __LPM(addr) __LPM_enhanced__(addr)
398 #define __LPM_word(addr) __LPM_word_enhanced__(addr)
399 #define __LPM_dword(addr) __LPM_dword_enhanced__(addr)
400 #define __LPM_float(addr) __LPM_float_enhanced__(addr)
401 #else
402 #define __LPM(addr) __LPM_classic__(addr)
403 #define __LPM_word(addr) __LPM_word_classic__(addr)
404 #define __LPM_dword(addr) __LPM_dword_classic__(addr)
405 #define __LPM_float(addr) __LPM_float_classic__(addr)
406 #endif
407 
414 #define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
415 
422 #define pgm_read_word_near(address_short) __LPM_word((uint16_t)(address_short))
423 
430 #define pgm_read_dword_near(address_short) \
431  __LPM_dword((uint16_t)(address_short))
432 
439 #define pgm_read_float_near(address_short) \
440  __LPM_float((uint16_t)(address_short))
441 
442 #if defined(RAMPZ) || defined(__DOXYGEN__)
443 
444 /* Only for devices with more than 64K of program memory.
445  RAMPZ must be defined (see iom103.h, iom128.h).
446 */
447 
448 /* The classic functions are needed for ATmega103. */
449 
450 #define __ELPM_classic__(addr) \
451 (__extension__({ \
452  uint32_t __addr32 = (uint32_t)(addr); \
453  uint8_t __result; \
454  __asm__ \
455  ( \
456  "out %2, %C1" "\n\t" \
457  "mov r31, %B1" "\n\t" \
458  "mov r30, %A1" "\n\t" \
459  "elpm" "\n\t" \
460  "mov %0, r0" "\n\t" \
461  : "=r" (__result) \
462  : "r" (__addr32), \
463  "I" (_SFR_IO_ADDR(RAMPZ)) \
464  : "r0", "r30", "r31" \
465  ); \
466  __result; \
467 }))
468 
469 #define __ELPM_enhanced__(addr) \
470 (__extension__({ \
471  uint32_t __addr32 = (uint32_t)(addr); \
472  uint8_t __result; \
473  __asm__ \
474  ( \
475  "out %2, %C1" "\n\t" \
476  "movw r30, %1" "\n\t" \
477  "elpm %0, Z+" "\n\t" \
478  : "=r" (__result) \
479  : "r" (__addr32), \
480  "I" (_SFR_IO_ADDR(RAMPZ)) \
481  : "r30", "r31" \
482  ); \
483  __result; \
484 }))
485 
486 #define __ELPM_xmega__(addr) \
487 (__extension__({ \
488  uint32_t __addr32 = (uint32_t)(addr); \
489  uint8_t __result; \
490  __asm__ \
491  ( \
492  "in __tmp_reg__, %2" "\n\t" \
493  "out %2, %C1" "\n\t" \
494  "movw r30, %1" "\n\t" \
495  "elpm %0, Z+" "\n\t" \
496  "out %2, __tmp_reg__" \
497  : "=r" (__result) \
498  : "r" (__addr32), \
499  "I" (_SFR_IO_ADDR(RAMPZ)) \
500  : "r30", "r31" \
501  ); \
502  __result; \
503 }))
504 
505 #define __ELPM_word_classic__(addr) \
506 (__extension__({ \
507  uint32_t __addr32 = (uint32_t)(addr); \
508  uint16_t __result; \
509  __asm__ \
510  ( \
511  "out %2, %C1" "\n\t" \
512  "mov r31, %B1" "\n\t" \
513  "mov r30, %A1" "\n\t" \
514  "elpm" "\n\t" \
515  "mov %A0, r0" "\n\t" \
516  "in r0, %2" "\n\t" \
517  "adiw r30, 1" "\n\t" \
518  "adc r0, __zero_reg__" "\n\t" \
519  "out %2, r0" "\n\t" \
520  "elpm" "\n\t" \
521  "mov %B0, r0" "\n\t" \
522  : "=r" (__result) \
523  : "r" (__addr32), \
524  "I" (_SFR_IO_ADDR(RAMPZ)) \
525  : "r0", "r30", "r31" \
526  ); \
527  __result; \
528 }))
529 
530 #define __ELPM_word_enhanced__(addr) \
531 (__extension__({ \
532  uint32_t __addr32 = (uint32_t)(addr); \
533  uint16_t __result; \
534  __asm__ \
535  ( \
536  "out %2, %C1" "\n\t" \
537  "movw r30, %1" "\n\t" \
538  "elpm %A0, Z+" "\n\t" \
539  "elpm %B0, Z" "\n\t" \
540  : "=r" (__result) \
541  : "r" (__addr32), \
542  "I" (_SFR_IO_ADDR(RAMPZ)) \
543  : "r30", "r31" \
544  ); \
545  __result; \
546 }))
547 
548 #define __ELPM_word_xmega__(addr) \
549 (__extension__({ \
550  uint32_t __addr32 = (uint32_t)(addr); \
551  uint16_t __result; \
552  __asm__ \
553  ( \
554  "in __tmp_reg__, %2" "\n\t" \
555  "out %2, %C1" "\n\t" \
556  "movw r30, %1" "\n\t" \
557  "elpm %A0, Z+" "\n\t" \
558  "elpm %B0, Z" "\n\t" \
559  "out %2, __tmp_reg__" \
560  : "=r" (__result) \
561  : "r" (__addr32), \
562  "I" (_SFR_IO_ADDR(RAMPZ)) \
563  : "r30", "r31" \
564  ); \
565  __result; \
566 }))
567 
568 #define __ELPM_dword_classic__(addr) \
569 (__extension__({ \
570  uint32_t __addr32 = (uint32_t)(addr); \
571  uint32_t __result; \
572  __asm__ \
573  ( \
574  "out %2, %C1" "\n\t" \
575  "mov r31, %B1" "\n\t" \
576  "mov r30, %A1" "\n\t" \
577  "elpm" "\n\t" \
578  "mov %A0, r0" "\n\t" \
579  "in r0, %2" "\n\t" \
580  "adiw r30, 1" "\n\t" \
581  "adc r0, __zero_reg__" "\n\t" \
582  "out %2, r0" "\n\t" \
583  "elpm" "\n\t" \
584  "mov %B0, r0" "\n\t" \
585  "in r0, %2" "\n\t" \
586  "adiw r30, 1" "\n\t" \
587  "adc r0, __zero_reg__" "\n\t" \
588  "out %2, r0" "\n\t" \
589  "elpm" "\n\t" \
590  "mov %C0, r0" "\n\t" \
591  "in r0, %2" "\n\t" \
592  "adiw r30, 1" "\n\t" \
593  "adc r0, __zero_reg__" "\n\t" \
594  "out %2, r0" "\n\t" \
595  "elpm" "\n\t" \
596  "mov %D0, r0" "\n\t" \
597  : "=r" (__result) \
598  : "r" (__addr32), \
599  "I" (_SFR_IO_ADDR(RAMPZ)) \
600  : "r0", "r30", "r31" \
601  ); \
602  __result; \
603 }))
604 
605 #define __ELPM_dword_enhanced__(addr) \
606 (__extension__({ \
607  uint32_t __addr32 = (uint32_t)(addr); \
608  uint32_t __result; \
609  __asm__ \
610  ( \
611  "out %2, %C1" "\n\t" \
612  "movw r30, %1" "\n\t" \
613  "elpm %A0, Z+" "\n\t" \
614  "elpm %B0, Z+" "\n\t" \
615  "elpm %C0, Z+" "\n\t" \
616  "elpm %D0, Z" "\n\t" \
617  : "=r" (__result) \
618  : "r" (__addr32), \
619  "I" (_SFR_IO_ADDR(RAMPZ)) \
620  : "r30", "r31" \
621  ); \
622  __result; \
623 }))
624 
625 #define __ELPM_dword_xmega__(addr) \
626 (__extension__({ \
627  uint32_t __addr32 = (uint32_t)(addr); \
628  uint32_t __result; \
629  __asm__ \
630  ( \
631  "in __tmp_reg__, %2" "\n\t" \
632  "out %2, %C1" "\n\t" \
633  "movw r30, %1" "\n\t" \
634  "elpm %A0, Z+" "\n\t" \
635  "elpm %B0, Z+" "\n\t" \
636  "elpm %C0, Z+" "\n\t" \
637  "elpm %D0, Z" "\n\t" \
638  "out %2, __tmp_reg__" \
639  : "=r" (__result) \
640  : "r" (__addr32), \
641  "I" (_SFR_IO_ADDR(RAMPZ)) \
642  : "r30", "r31" \
643  ); \
644  __result; \
645 }))
646 
647 #define __ELPM_float_classic__(addr) \
648 (__extension__({ \
649  uint32_t __addr32 = (uint32_t)(addr); \
650  float __result; \
651  __asm__ \
652  ( \
653  "out %2, %C1" "\n\t" \
654  "mov r31, %B1" "\n\t" \
655  "mov r30, %A1" "\n\t" \
656  "elpm" "\n\t" \
657  "mov %A0, r0" "\n\t" \
658  "in r0, %2" "\n\t" \
659  "adiw r30, 1" "\n\t" \
660  "adc r0, __zero_reg__" "\n\t" \
661  "out %2, r0" "\n\t" \
662  "elpm" "\n\t" \
663  "mov %B0, r0" "\n\t" \
664  "in r0, %2" "\n\t" \
665  "adiw r30, 1" "\n\t" \
666  "adc r0, __zero_reg__" "\n\t" \
667  "out %2, r0" "\n\t" \
668  "elpm" "\n\t" \
669  "mov %C0, r0" "\n\t" \
670  "in r0, %2" "\n\t" \
671  "adiw r30, 1" "\n\t" \
672  "adc r0, __zero_reg__" "\n\t" \
673  "out %2, r0" "\n\t" \
674  "elpm" "\n\t" \
675  "mov %D0, r0" "\n\t" \
676  : "=r" (__result) \
677  : "r" (__addr32), \
678  "I" (_SFR_IO_ADDR(RAMPZ)) \
679  : "r0", "r30", "r31" \
680  ); \
681  __result; \
682 }))
683 
684 #define __ELPM_float_enhanced__(addr) \
685 (__extension__({ \
686  uint32_t __addr32 = (uint32_t)(addr); \
687  float __result; \
688  __asm__ \
689  ( \
690  "out %2, %C1" "\n\t" \
691  "movw r30, %1" "\n\t" \
692  "elpm %A0, Z+" "\n\t" \
693  "elpm %B0, Z+" "\n\t" \
694  "elpm %C0, Z+" "\n\t" \
695  "elpm %D0, Z" "\n\t" \
696  : "=r" (__result) \
697  : "r" (__addr32), \
698  "I" (_SFR_IO_ADDR(RAMPZ)) \
699  : "r30", "r31" \
700  ); \
701  __result; \
702 }))
703 
704 #define __ELPM_float_xmega__(addr) \
705 (__extension__({ \
706  uint32_t __addr32 = (uint32_t)(addr); \
707  float __result; \
708  __asm__ \
709  ( \
710  "in __tmp_reg__, %2" "\n\t" \
711  "out %2, %C1" "\n\t" \
712  "movw r30, %1" "\n\t" \
713  "elpm %A0, Z+" "\n\t" \
714  "elpm %B0, Z+" "\n\t" \
715  "elpm %C0, Z+" "\n\t" \
716  "elpm %D0, Z" "\n\t" \
717  "out %2, __tmp_reg__" \
718  : "=r" (__result) \
719  : "r" (__addr32), \
720  "I" (_SFR_IO_ADDR(RAMPZ)) \
721  : "r30", "r31" \
722  ); \
723  __result; \
724 }))
725 
726 /*
727 Check for architectures that implement RAMPD (avrxmega3, avrxmega5,
728 avrxmega7) as they need to save/restore RAMPZ for ELPM macros so it does
729 not interfere with data accesses.
730 */
731 #if defined (__AVR_HAVE_RAMPD__)
732 
733 #define __ELPM(addr) __ELPM_xmega__(addr)
734 #define __ELPM_word(addr) __ELPM_word_xmega__(addr)
735 #define __ELPM_dword(addr) __ELPM_dword_xmega__(addr)
736 #define __ELPM_float(addr) __ELPM_float_xmega__(addr)
737 
738 #else
739 
740 #if defined (__AVR_HAVE_LPMX__)
741 
742 #define __ELPM(addr) __ELPM_enhanced__(addr)
743 #define __ELPM_word(addr) __ELPM_word_enhanced__(addr)
744 #define __ELPM_dword(addr) __ELPM_dword_enhanced__(addr)
745 #define __ELPM_float(addr) __ELPM_float_enhanced__(addr)
746 
747 #else
748 
749 #define __ELPM(addr) __ELPM_classic__(addr)
750 #define __ELPM_word(addr) __ELPM_word_classic__(addr)
751 #define __ELPM_dword(addr) __ELPM_dword_classic__(addr)
752 #define __ELPM_float(addr) __ELPM_float_classic__(addr)
753 
754 #endif /* __AVR_HAVE_LPMX__ */
755 
756 #endif /* __AVR_HAVE_RAMPD__ */
757 
758 
766 #define pgm_read_byte_far(address_long) __ELPM((uint32_t)(address_long))
767 
775 #define pgm_read_word_far(address_long) __ELPM_word((uint32_t)(address_long))
776 
784 #define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long))
785 
793 #define pgm_read_float_far(address_long) __ELPM_float((uint32_t)(address_long))
794 
795 #endif /* RAMPZ or __DOXYGEN__ */
796 
804 #define pgm_read_byte(address_short) pgm_read_byte_near(address_short)
805 
813 #define pgm_read_word(address_short) pgm_read_word_near(address_short)
814 
822 #define pgm_read_dword(address_short) pgm_read_dword_near(address_short)
823 
831 #define pgm_read_float(address_short) pgm_read_float_near(address_short)
832 
839 #ifndef PGM_P
840 #define PGM_P const prog_char *
841 #endif
842 
848 #ifndef PGM_VOID_P
849 #define PGM_VOID_P const prog_void *
850 #endif
851 
852 extern PGM_VOID_P memchr_P(PGM_VOID_P, int __val, size_t __len) __ATTR_CONST__;
853 extern int memcmp_P(const void *, PGM_VOID_P, size_t) __ATTR_PURE__;
854 extern void *memccpy_P(void *, PGM_VOID_P, int __val, size_t);
855 extern void *memcpy_P(void *, PGM_VOID_P, size_t);
856 extern void *memmem_P(const void *, size_t, PGM_VOID_P, size_t) __ATTR_PURE__;
857 extern PGM_VOID_P memrchr_P(PGM_VOID_P, int __val, size_t __len) __ATTR_CONST__;
858 extern char *strcat_P(char *, PGM_P);
859 extern PGM_P strchr_P(PGM_P, int __val) __ATTR_CONST__;
860 extern PGM_P strchrnul_P(PGM_P, int __val) __ATTR_CONST__;
861 extern int strcmp_P(const char *, PGM_P) __ATTR_PURE__;
862 extern char *strcpy_P(char *, PGM_P);
863 extern int strcasecmp_P(const char *, PGM_P) __ATTR_PURE__;
864 extern char *strcasestr_P(const char *, PGM_P) __ATTR_PURE__;
865 extern size_t strcspn_P(const char *__s, PGM_P __reject) __ATTR_PURE__;
866 extern size_t strlcat_P (char *, PGM_P, size_t );
867 extern size_t strlcpy_P (char *, PGM_P, size_t );
868 extern size_t strlen_P(PGM_P) __ATTR_CONST__; /* program memory can't change */
869 extern size_t strnlen_P(PGM_P, size_t) __ATTR_CONST__; /* program memory can't change */
870 extern int strncmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;
871 extern int strncasecmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;
872 extern char *strncat_P(char *, PGM_P, size_t);
873 extern char *strncpy_P(char *, PGM_P, size_t);
874 extern char *strpbrk_P(const char *__s, PGM_P __accept) __ATTR_PURE__;
875 extern PGM_P strrchr_P(PGM_P, int __val) __ATTR_CONST__;
876 extern char *strsep_P(char **__sp, PGM_P __delim);
877 extern size_t strspn_P(const char *__s, PGM_P __accept) __ATTR_PURE__;
878 extern char *strstr_P(const char *, PGM_P) __ATTR_PURE__;
879 extern char *strtok_P(char *__s, PGM_P __delim);
880 extern char *strtok_rP(char *__s, PGM_P __delim, char **__last);
881 
882 #ifdef __cplusplus
883 }
884 #endif
885 
887 #endif /* __PGMSPACE_H_ */
#define PGM_VOID_P
Used to declare a generic pointer to an object in program space.
Definition: pgmspace.h:849
#define PGM_P
Used to declare a variable that is a pointer to a string in program space.
Definition: pgmspace.h:840
AVR device-specific IO Definitions.
#define PROGMEM
Attribute to use in order to declare an object being located in flash ROM.
Definition: pgmspace.h:107