AVR Libc Home Page AVRs AVR Libc Development Pages
Main Page User Manual Library Reference FAQ Alphabetical Index Example Projects

pgmspace.h

Go to the documentation of this file.
00001 /* Copyright (c) 2002-2007  Marek Michalkiewicz
00002    Copyright (c) 2006, Carlos Lamas
00003    Copyright (c) 2009-2010, Jan Waclawek
00004    All rights reserved.
00005 
00006    Redistribution and use in source and binary forms, with or without
00007    modification, are permitted provided that the following conditions are met:
00008 
00009    * Redistributions of source code must retain the above copyright
00010      notice, this list of conditions and the following disclaimer.
00011    * Redistributions in binary form must reproduce the above copyright
00012      notice, this list of conditions and the following disclaimer in
00013      the documentation and/or other materials provided with the
00014      distribution.
00015    * Neither the name of the copyright holders nor the names of
00016      contributors may be used to endorse or promote products derived
00017      from this software without specific prior written permission.
00018 
00019   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029   POSSIBILITY OF SUCH DAMAGE. */
00030 
00031 /* $Id$ */
00032 
00033 /*
00034    pgmspace.h
00035 
00036    Contributors:
00037      Created by Marek Michalkiewicz <marekm@linux.org.pl>
00038      Eric B. Weddington <eric@ecentral.com>
00039      Wolfgang Haidinger <wh@vmars.tuwien.ac.at> (pgm_read_dword())
00040      Ivanov Anton <anton@arc.com.ru> (pgm_read_float())
00041  */
00042 
00043 /** \file */
00044 /** \defgroup avr_pgmspace <avr/pgmspace.h>: Program Space Utilities
00045     \code
00046     #include <avr/io.h>
00047     #include <avr/pgmspace.h>
00048     \endcode
00049 
00050     The functions in this module provide interfaces for a program to access
00051     data stored in program space (flash memory) of the device.  In order to
00052     use these functions, the target device must support either the \c LPM or
00053     \c ELPM instructions.
00054 
00055     \note These functions are an attempt to provide some compatibility with
00056     header files that come with IAR C, to make porting applications between
00057     different compilers easier.  This is not 100% compatibility though (GCC
00058     does not have full support for multiple address spaces yet).
00059 
00060     \note If you are working with strings which are completely based in ram,
00061     use the standard string functions described in \ref avr_string.
00062 
00063     \note If possible, put your constant tables in the lower 64 KB and use
00064     pgm_read_byte_near() or pgm_read_word_near() instead of
00065     pgm_read_byte_far() or pgm_read_word_far() since it is more efficient that
00066     way, and you can still use the upper 64K for executable code.
00067     All functions that are suffixed with a \c _P \e require their
00068     arguments to be in the lower 64 KB of the flash ROM, as they do
00069     not use ELPM instructions.  This is normally not a big concern as
00070     the linker setup arranges any program space constants declared
00071     using the macros from this header file so they are placed right after
00072     the interrupt vectors, and in front of any executable code.  However,
00073     it can become a problem if there are too many of these constants, or
00074     for bootloaders on devices with more than 64 KB of ROM.
00075     <em>All these functions will not work in that situation.</em>
00076 
00077     \note For <b>Xmega</b> devices, make sure the NVM controller
00078     command register (\c NVM.CMD or \c NVM_CMD) is set to 0x00 (NOP)
00079     before using any of these functions.
00080 */
00081 
00082 #ifndef __PGMSPACE_H_
00083 #define __PGMSPACE_H_ 1
00084 
00085 #define __need_size_t
00086 #include <inttypes.h>
00087 #include <stddef.h>
00088 #include <avr/io.h>
00089 
00090 #ifndef __ATTR_CONST__
00091 #define __ATTR_CONST__ __attribute__((__const__))
00092 #endif
00093 
00094 #ifndef __ATTR_PROGMEM__
00095 #define __ATTR_PROGMEM__ __attribute__((__progmem__))
00096 #endif
00097 
00098 #ifndef __ATTR_PURE__
00099 #define __ATTR_PURE__ __attribute__((__pure__))
00100 #endif
00101 
00102 /**
00103    \ingroup avr_pgmspace
00104    \def PROGMEM
00105 
00106    Attribute to use in order to declare an object being located in
00107    flash ROM.
00108  */
00109 #define PROGMEM __ATTR_PROGMEM__
00110 
00111 #ifdef __cplusplus
00112 extern "C" {
00113 #endif
00114 
00115 #if defined(__DOXYGEN__)
00116 /*
00117  * Doxygen doesn't grok the appended attribute syntax of
00118  * GCC, and confuses the typedefs with function decls, so
00119  * supply a doxygen-friendly view.
00120  */
00121 
00122 /**
00123    \ingroup avr_pgmspace
00124    \typedef prog_void
00125    \note DEPRECATED
00126 
00127    This typedef is now deprecated because the usage of the __progmem__ 
00128    attribute on a type is not supported in GCC. However, the use of the 
00129    __progmem__ attribute on a variable declaration is supported, and this is 
00130    now the recommended usage.
00131 
00132    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00133    has been defined before including <avr/pgmspace.h> (either by a
00134    #define directive, or by a -D compiler option.)
00135 
00136    Type of a "void" object located in flash ROM.  Does not make much
00137    sense by itself, but can be used to declare a "void *" object in
00138    flash ROM.
00139 */
00140 typedef void PROGMEM prog_void;
00141 
00142 /**
00143    \ingroup avr_pgmspace
00144    \typedef prog_char
00145    \note DEPRECATED
00146 
00147    This typedef is now deprecated because the usage of the __progmem__ 
00148    attribute on a type is not supported in GCC. However, the use of the 
00149    __progmem__ attribute on a variable declaration is supported, and this is 
00150    now the recommended usage.
00151 
00152    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00153    has been defined before including <avr/pgmspace.h> (either by a
00154    #define directive, or by a -D compiler option.)
00155 
00156    Type of a "char" object located in flash ROM.
00157 */
00158 typedef char PROGMEM prog_char;
00159 
00160 /**
00161    \ingroup avr_pgmspace
00162    \typedef prog_uchar
00163    \note DEPRECATED
00164 
00165    This typedef is now deprecated because the usage of the __progmem__ 
00166    attribute on a type is not supported in GCC. However, the use of the 
00167    __progmem__ attribute on a variable declaration is supported, and this is 
00168    now the recommended usage.
00169 
00170    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00171    has been defined before including <avr/pgmspace.h> (either by a
00172    #define directive, or by a -D compiler option.)
00173 
00174    Type of an "unsigned char" object located in flash ROM.
00175 */
00176 typedef unsigned char PROGMEM prog_uchar;
00177 
00178 /**
00179    \ingroup avr_pgmspace
00180    \typedef prog_int8_t
00181    \note DEPRECATED
00182 
00183    This typedef is now deprecated because the usage of the __progmem__ 
00184    attribute on a type is not supported in GCC. However, the use of the 
00185    __progmem__ attribute on a variable declaration is supported, and this is 
00186    now the recommended usage.
00187 
00188    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00189    has been defined before including <avr/pgmspace.h> (either by a
00190    #define directive, or by a -D compiler option.)
00191 
00192    Type of an "int8_t" object located in flash ROM.
00193 */
00194 typedef int8_t PROGMEM prog_int8_t;
00195 
00196 /**
00197    \ingroup avr_pgmspace
00198    \typedef prog_uint8_t
00199    \note DEPRECATED
00200 
00201    This typedef is now deprecated because the usage of the __progmem__ 
00202    attribute on a type is not supported in GCC. However, the use of the 
00203    __progmem__ attribute on a variable declaration is supported, and this is 
00204    now the recommended usage.
00205 
00206    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00207    has been defined before including <avr/pgmspace.h> (either by a
00208    #define directive, or by a -D compiler option.)
00209 
00210    Type of an "uint8_t" object located in flash ROM.
00211 */
00212 typedef uint8_t PROGMEM prog_uint8_t;
00213 
00214 /**
00215    \ingroup avr_pgmspace
00216    \typedef prog_int16_t
00217    \note DEPRECATED
00218 
00219    This typedef is now deprecated because the usage of the __progmem__ 
00220    attribute on a type is not supported in GCC. However, the use of the 
00221    __progmem__ attribute on a variable declaration is supported, and this is 
00222    now the recommended usage.
00223 
00224    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00225    has been defined before including <avr/pgmspace.h> (either by a
00226    #define directive, or by a -D compiler option.)
00227 
00228    Type of an "int16_t" object located in flash ROM.
00229 */
00230 typedef int16_t PROGMEM prog_int16_t;
00231 
00232 /**
00233    \ingroup avr_pgmspace
00234    \typedef prog_uint16_t
00235    \note DEPRECATED
00236 
00237    This typedef is now deprecated because the usage of the __progmem__ 
00238    attribute on a type is not supported in GCC. However, the use of the 
00239    __progmem__ attribute on a variable declaration is supported, and this is 
00240    now the recommended usage.
00241 
00242    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00243    has been defined before including <avr/pgmspace.h> (either by a
00244    #define directive, or by a -D compiler option.)
00245 
00246    Type of an "uint16_t" object located in flash ROM.
00247 */
00248 typedef uint16_t PROGMEM prog_uint16_t;
00249 
00250 /**
00251    \ingroup avr_pgmspace
00252    \typedef prog_int32_t
00253    \note DEPRECATED
00254 
00255    This typedef is now deprecated because the usage of the __progmem__ 
00256    attribute on a type is not supported in GCC. However, the use of the 
00257    __progmem__ attribute on a variable declaration is supported, and this is 
00258    now the recommended usage.
00259 
00260    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00261    has been defined before including <avr/pgmspace.h> (either by a
00262    #define directive, or by a -D compiler option.)
00263 
00264    Type of an "int32_t" object located in flash ROM.
00265 */
00266 typedef int32_t PROGMEM prog_int32_t;
00267 
00268 /**
00269    \ingroup avr_pgmspace
00270    \typedef prog_uint32_t
00271    \note DEPRECATED
00272 
00273    This typedef is now deprecated because the usage of the __progmem__ 
00274    attribute on a type is not supported in GCC. However, the use of the 
00275    __progmem__ attribute on a variable declaration is supported, and this is 
00276    now the recommended usage.
00277 
00278    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00279    has been defined before including <avr/pgmspace.h> (either by a
00280    #define directive, or by a -D compiler option.)
00281 
00282    Type of an "uint32_t" object located in flash ROM.
00283 */
00284 typedef uint32_t PROGMEM prog_uint32_t;
00285 
00286 /**
00287    \ingroup avr_pgmspace
00288    \typedef prog_int64_t
00289    \note DEPRECATED
00290 
00291    This typedef is now deprecated because the usage of the __progmem__ 
00292    attribute on a type is not supported in GCC. However, the use of the 
00293    __progmem__ attribute on a variable declaration is supported, and this is 
00294    now the recommended usage.
00295 
00296    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00297    has been defined before including <avr/pgmspace.h> (either by a
00298    #define directive, or by a -D compiler option.)
00299 
00300    Type of an "int64_t" object located in flash ROM.
00301 
00302    \note This type is not available when the compiler
00303    option -mint8 is in effect.
00304 */
00305 typedef int64_t PROGMEM prog_int64_t;
00306 
00307 /**
00308    \ingroup avr_pgmspace
00309    \typedef prog_uint64_t
00310    \note DEPRECATED
00311 
00312    This typedef is now deprecated because the usage of the __progmem__ 
00313    attribute on a type is not supported in GCC. However, the use of the 
00314    __progmem__ attribute on a variable declaration is supported, and this is 
00315    now the recommended usage.
00316 
00317    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00318    has been defined before including <avr/pgmspace.h> (either by a
00319    #define directive, or by a -D compiler option.)
00320 
00321    Type of an "uint64_t" object located in flash ROM.
00322 
00323    \note This type is not available when the compiler
00324    option -mint8 is in effect.
00325 */
00326 typedef uint64_t PROGMEM prog_uint64_t;
00327 
00328 /** \ingroup avr_pgmspace
00329     \def PGM_P
00330 
00331     Used to declare a variable that is a pointer to a string in program
00332     space. */
00333 
00334 #ifndef PGM_P
00335 #define PGM_P const char *
00336 #endif
00337 
00338 /** \ingroup avr_pgmspace
00339     \def PGM_VOID_P
00340 
00341     Used to declare a generic pointer to an object in program space. */
00342 
00343 #ifndef PGM_VOID_P
00344 #define PGM_VOID_P const void *
00345 #endif
00346 
00347 #elif defined(__PROG_TYPES_COMPAT__)  /* !DOXYGEN */
00348 
00349 typedef void prog_void __attribute__((__progmem__,deprecated("prog_void type is deprecated.")));
00350 typedef char prog_char __attribute__((__progmem__,deprecated("prog_char type is deprecated.")));
00351 typedef unsigned char prog_uchar __attribute__((__progmem__,deprecated("prog_uchar type is deprecated.")));
00352 typedef int8_t    prog_int8_t   __attribute__((__progmem__,deprecated("prog_int8_t type is deprecated.")));
00353 typedef uint8_t   prog_uint8_t  __attribute__((__progmem__,deprecated("prog_uint8_t type is deprecated.")));
00354 typedef int16_t   prog_int16_t  __attribute__((__progmem__,deprecated("prog_int16_t type is deprecated.")));
00355 typedef uint16_t  prog_uint16_t __attribute__((__progmem__,deprecated("prog_uint16_t type is deprecated.")));
00356 typedef int32_t   prog_int32_t  __attribute__((__progmem__,deprecated("prog_int32_t type is deprecated.")));
00357 typedef uint32_t  prog_uint32_t __attribute__((__progmem__,deprecated("prog_uint32_t type is deprecated.")));
00358 #if !__USING_MINT8
00359 typedef int64_t   prog_int64_t  __attribute__((__progmem__,deprecated("prog_int64_t type is deprecated.")));
00360 typedef uint64_t  prog_uint64_t __attribute__((__progmem__,deprecated("prog_uint64_t type is deprecated.")));
00361 #endif
00362 
00363 #ifndef PGM_P
00364 #define PGM_P const prog_char *
00365 #endif
00366 
00367 #ifndef PGM_VOID_P
00368 #define PGM_VOID_P const prog_void *
00369 #endif
00370 
00371 #else /* !defined(__DOXYGEN__), !defined(__PROG_TYPES_COMPAT__) */
00372 
00373 #ifndef PGM_P
00374 #define PGM_P const char *
00375 #endif
00376 
00377 #ifndef PGM_VOID_P
00378 #define PGM_VOID_P const void *
00379 #endif
00380 #endif /* defined(__DOXYGEN__), defined(__PROG_TYPES_COMPAT__) */
00381 
00382 /* Although in C, we can get away with just using __c, it does not work in
00383    C++. We need to use &__c[0] to avoid the compiler puking. Dave Hylands
00384    explaned it thusly,
00385 
00386      Let's suppose that we use PSTR("Test"). In this case, the type returned
00387      by __c is a prog_char[5] and not a prog_char *. While these are
00388      compatible, they aren't the same thing (especially in C++). The type
00389      returned by &__c[0] is a prog_char *, which explains why it works
00390      fine. */
00391 
00392 #if defined(__DOXYGEN__)
00393 /*
00394  * The #define below is just a dummy that serves documentation
00395  * purposes only.
00396  */
00397 /** \ingroup avr_pgmspace
00398     \def PSTR(s)
00399 
00400     Used to declare a static pointer to a string in program space. */
00401 # define PSTR(s) ((const PROGMEM char *)(s))
00402 #else  /* !DOXYGEN */
00403 /* The real thing. */
00404 # define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
00405 #endif /* DOXYGEN */
00406 
00407 #define __LPM_classic__(addr)   \
00408 (__extension__({                \
00409     uint16_t __addr16 = (uint16_t)(addr); \
00410     uint8_t __result;           \
00411     __asm__ __volatile__        \
00412     (                           \
00413         "lpm" "\n\t"            \
00414         "mov %0, r0" "\n\t"     \
00415         : "=r" (__result)       \
00416         : "z" (__addr16)        \
00417         : "r0"                  \
00418     );                          \
00419     __result;                   \
00420 }))
00421 
00422 #define __LPM_tiny__(addr)      \
00423 (__extension__({                \
00424     uint16_t __addr16 = (uint16_t)(addr) + __AVR_TINY_PM_BASE_ADDRESS__; \
00425     uint8_t __result;           \
00426     __asm__                     \
00427     (                           \
00428         "ld %0, z" "\n\t"       \
00429         : "=r" (__result)       \
00430         : "z" (__addr16)        \
00431     );                          \
00432     __result;                   \
00433 }))
00434 
00435 #define __LPM_enhanced__(addr)  \
00436 (__extension__({                \
00437     uint16_t __addr16 = (uint16_t)(addr); \
00438     uint8_t __result;           \
00439     __asm__ __volatile__        \
00440     (                           \
00441         "lpm %0, Z" "\n\t"      \
00442         : "=r" (__result)       \
00443         : "z" (__addr16)        \
00444     );                          \
00445     __result;                   \
00446 }))
00447 
00448 #define __LPM_word_classic__(addr)          \
00449 (__extension__({                            \
00450     uint16_t __addr16 = (uint16_t)(addr);   \
00451     uint16_t __result;                      \
00452     __asm__ __volatile__                    \
00453     (                                       \
00454         "lpm"           "\n\t"              \
00455         "mov %A0, r0"   "\n\t"              \
00456         "adiw r30, 1"   "\n\t"              \
00457         "lpm"           "\n\t"              \
00458         "mov %B0, r0"   "\n\t"              \
00459         : "=r" (__result), "=z" (__addr16)  \
00460         : "1" (__addr16)                    \
00461         : "r0"                              \
00462     );                                      \
00463     __result;                               \
00464 }))
00465 
00466 #define __LPM_word_tiny__(addr)             \
00467 (__extension__({                            \
00468     uint16_t __addr16 = (uint16_t)(addr) + __AVR_TINY_PM_BASE_ADDRESS__; \
00469     uint16_t __result;                      \
00470     __asm__                                 \
00471     (                                       \
00472         "ld %A0, z+"     "\n\t"             \
00473         "ld %B0, z"      "\n\t"             \
00474         : "=r" (__result), "=z" (__addr16)  \
00475         : "1" (__addr16)                    \
00476     );                                      \
00477     __result;                               \
00478 }))
00479 
00480 #define __LPM_word_enhanced__(addr)         \
00481 (__extension__({                            \
00482     uint16_t __addr16 = (uint16_t)(addr);   \
00483     uint16_t __result;                      \
00484     __asm__ __volatile__                    \
00485     (                                       \
00486         "lpm %A0, Z+"   "\n\t"              \
00487         "lpm %B0, Z"    "\n\t"              \
00488         : "=r" (__result), "=z" (__addr16)  \
00489         : "1" (__addr16)                    \
00490     );                                      \
00491     __result;                               \
00492 }))
00493 
00494 #define __LPM_dword_classic__(addr)         \
00495 (__extension__({                            \
00496     uint16_t __addr16 = (uint16_t)(addr);   \
00497     uint32_t __result;                      \
00498     __asm__ __volatile__                    \
00499     (                                       \
00500         "lpm"           "\n\t"              \
00501         "mov %A0, r0"   "\n\t"              \
00502         "adiw r30, 1"   "\n\t"              \
00503         "lpm"           "\n\t"              \
00504         "mov %B0, r0"   "\n\t"              \
00505         "adiw r30, 1"   "\n\t"              \
00506         "lpm"           "\n\t"              \
00507         "mov %C0, r0"   "\n\t"              \
00508         "adiw r30, 1"   "\n\t"              \
00509         "lpm"           "\n\t"              \
00510         "mov %D0, r0"   "\n\t"              \
00511         : "=r" (__result), "=z" (__addr16)  \
00512         : "1" (__addr16)                    \
00513         : "r0"                              \
00514     );                                      \
00515     __result;                               \
00516 }))
00517 
00518 #define __LPM_dword_tiny__(addr)            \
00519 (__extension__({                            \
00520     uint16_t __addr16 = (uint16_t)(addr) + __AVR_TINY_PM_BASE_ADDRESS__; \
00521     uint32_t __result;                      \
00522     __asm__                                 \
00523     (                                       \
00524         "ld %A0, z+"    "\n\t"              \
00525         "ld %B0, z+"    "\n\t"              \
00526         "ld %C0, z+"    "\n\t"              \
00527         "ld %D0, z"     "\n\t"              \
00528         : "=r" (__result), "=z" (__addr16)  \
00529         : "1" (__addr16)                    \
00530     );                                      \
00531     __result;                               \
00532 }))
00533 
00534 #define __LPM_dword_enhanced__(addr)        \
00535 (__extension__({                            \
00536     uint16_t __addr16 = (uint16_t)(addr);   \
00537     uint32_t __result;                      \
00538     __asm__ __volatile__                    \
00539     (                                       \
00540         "lpm %A0, Z+"   "\n\t"              \
00541         "lpm %B0, Z+"   "\n\t"              \
00542         "lpm %C0, Z+"   "\n\t"              \
00543         "lpm %D0, Z"    "\n\t"              \
00544         : "=r" (__result), "=z" (__addr16)  \
00545         : "1" (__addr16)                    \
00546     );                                      \
00547     __result;                               \
00548 }))
00549 
00550 #define __LPM_float_classic__(addr)         \
00551 (__extension__({                            \
00552     uint16_t __addr16 = (uint16_t)(addr);   \
00553     float __result;                         \
00554     __asm__ __volatile__                    \
00555     (                                       \
00556         "lpm"           "\n\t"              \
00557         "mov %A0, r0"   "\n\t"              \
00558         "adiw r30, 1"   "\n\t"              \
00559         "lpm"           "\n\t"              \
00560         "mov %B0, r0"   "\n\t"              \
00561         "adiw r30, 1"   "\n\t"              \
00562         "lpm"           "\n\t"              \
00563         "mov %C0, r0"   "\n\t"              \
00564         "adiw r30, 1"   "\n\t"              \
00565         "lpm"           "\n\t"              \
00566         "mov %D0, r0"   "\n\t"              \
00567         : "=r" (__result), "=z" (__addr16)  \
00568         : "1" (__addr16)                    \
00569         : "r0"                              \
00570     );                                      \
00571     __result;                               \
00572 }))
00573 
00574 #define __LPM_float_tiny__(addr)            \
00575 (__extension__({                            \
00576     uint16_t __addr16 = (uint16_t)(addr) + __AVR_TINY_PM_BASE_ADDRESS__; \
00577     float __result;                         \
00578     __asm__                                 \
00579     (                                       \
00580         "ld %A0, z+"   "\n\t"               \
00581         "ld %B0, z+"   "\n\t"               \
00582         "ld %C0, z+"   "\n\t"               \
00583         "ld %D0, z"    "\n\t"               \
00584         : "=r" (__result), "=z" (__addr16)  \
00585         : "1" (__addr16)                    \
00586     );                                      \
00587     __result;                               \
00588 }))
00589 
00590 #define __LPM_float_enhanced__(addr)        \
00591 (__extension__({                            \
00592     uint16_t __addr16 = (uint16_t)(addr);   \
00593     float __result;                         \
00594     __asm__ __volatile__                    \
00595     (                                       \
00596         "lpm %A0, Z+"   "\n\t"              \
00597         "lpm %B0, Z+"   "\n\t"              \
00598         "lpm %C0, Z+"   "\n\t"              \
00599         "lpm %D0, Z"    "\n\t"              \
00600         : "=r" (__result), "=z" (__addr16)  \
00601         : "1" (__addr16)                    \
00602     );                                      \
00603     __result;                               \
00604 }))
00605 
00606 #if defined (__AVR_HAVE_LPMX__)
00607 #define __LPM(addr)         __LPM_enhanced__(addr)
00608 #define __LPM_word(addr)    __LPM_word_enhanced__(addr)
00609 #define __LPM_dword(addr)   __LPM_dword_enhanced__(addr)
00610 #define __LPM_float(addr)   __LPM_float_enhanced__(addr)
00611 /*
00612 Macro to read data from program memory for avr tiny parts(tiny 4/5/9/10/20/40).
00613 why:
00614 - LPM instruction is not available in AVR_TINY instruction set.
00615 - Programs are executed starting from address 0x0000 in program memory.
00616 But it must be addressed starting from 0x4000 when accessed via data memory.
00617 Reference: TINY device (ATTiny 4,5,9,10,20 and 40) datasheets
00618 Bug: avrtc-536
00619 */
00620 #elif defined (__AVR_TINY__)
00621 #define __LPM(addr)         __LPM_tiny__(addr)
00622 #define __LPM_word(addr)    __LPM_word_tiny__(addr)
00623 #define __LPM_dword(addr)   __LPM_dword_tiny__(addr)
00624 #define __LPM_float(addr)   __LPM_float_tiny__(addr)
00625 #else
00626 #define __LPM(addr)         __LPM_classic__(addr)
00627 #define __LPM_word(addr)    __LPM_word_classic__(addr)
00628 #define __LPM_dword(addr)   __LPM_dword_classic__(addr)
00629 #define __LPM_float(addr)   __LPM_float_classic__(addr)
00630 #endif
00631 
00632 /** \ingroup avr_pgmspace
00633     \def pgm_read_byte_near(address_short)
00634     Read a byte from the program space with a 16-bit (near) address. 
00635     \note The address is a byte address.
00636     The address is in the program space. */
00637 
00638 #define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
00639 
00640 /** \ingroup avr_pgmspace
00641     \def pgm_read_word_near(address_short)
00642     Read a word from the program space with a 16-bit (near) address. 
00643     \note The address is a byte address. 
00644     The address is in the program space. */
00645 
00646 #define pgm_read_word_near(address_short) __LPM_word((uint16_t)(address_short))
00647 
00648 /** \ingroup avr_pgmspace
00649     \def pgm_read_dword_near(address_short)
00650     Read a double word from the program space with a 16-bit (near) address. 
00651     \note The address is a byte address. 
00652     The address is in the program space. */
00653 
00654 #define pgm_read_dword_near(address_short) \
00655     __LPM_dword((uint16_t)(address_short))
00656 
00657 /** \ingroup avr_pgmspace
00658     \def pgm_read_float_near(address_short)
00659     Read a float from the program space with a 16-bit (near) address. 
00660     \note The address is a byte address. 
00661     The address is in the program space. */
00662 
00663 #define pgm_read_float_near(address_short) \
00664     __LPM_float((uint16_t)(address_short))
00665 
00666 /** \ingroup avr_pgmspace
00667     \def pgm_read_ptr_near(address_short)
00668     Read a pointer from the program space with a 16-bit (near) address. 
00669     \note The address is a byte address. 
00670     The address is in the program space. */
00671 
00672 #define pgm_read_ptr_near(address_short) \
00673     (void*)__LPM_word((uint16_t)(address_short))
00674 
00675 #if defined(RAMPZ) || defined(__DOXYGEN__)
00676 
00677 /* Only for devices with more than 64K of program memory.
00678    RAMPZ must be defined (see iom103.h, iom128.h).
00679 */
00680 
00681 /* The classic functions are needed for ATmega103. */
00682 
00683 #define __ELPM_classic__(addr)      \
00684 (__extension__({                    \
00685     uint32_t __addr32 = (uint32_t)(addr); \
00686     uint8_t __result;               \
00687     __asm__ __volatile__            \
00688     (                               \
00689         "out %2, %C1" "\n\t"        \
00690         "mov r31, %B1" "\n\t"       \
00691         "mov r30, %A1" "\n\t"       \
00692         "elpm" "\n\t"               \
00693         "mov %0, r0" "\n\t"         \
00694         : "=r" (__result)           \
00695         : "r" (__addr32),           \
00696           "I" (_SFR_IO_ADDR(RAMPZ)) \
00697         : "r0", "r30", "r31"        \
00698     );                              \
00699     __result;                       \
00700 }))
00701 
00702 #define __ELPM_enhanced__(addr)     \
00703 (__extension__({                    \
00704     uint32_t __addr32 = (uint32_t)(addr); \
00705     uint8_t __result;               \
00706     __asm__ __volatile__            \
00707     (                               \
00708         "out %2, %C1" "\n\t"        \
00709         "movw r30, %1" "\n\t"       \
00710         "elpm %0, Z+" "\n\t"        \
00711         : "=r" (__result)           \
00712         : "r" (__addr32),           \
00713           "I" (_SFR_IO_ADDR(RAMPZ)) \
00714         : "r30", "r31"              \
00715     );                              \
00716     __result;                       \
00717 }))
00718 
00719 #define __ELPM_xmega__(addr)        \
00720 (__extension__({                    \
00721     uint32_t __addr32 = (uint32_t)(addr); \
00722     uint8_t __result;               \
00723     __asm__ __volatile__            \
00724     (                               \
00725         "in __tmp_reg__, %2" "\n\t" \
00726         "out %2, %C1" "\n\t"        \
00727         "movw r30, %1" "\n\t"       \
00728         "elpm %0, Z+" "\n\t"        \
00729         "out %2, __tmp_reg__"       \
00730         : "=r" (__result)           \
00731         : "r" (__addr32),           \
00732           "I" (_SFR_IO_ADDR(RAMPZ)) \
00733         : "r30", "r31"              \
00734     );                              \
00735     __result;                       \
00736 }))
00737 
00738 #define __ELPM_word_classic__(addr)     \
00739 (__extension__({                        \
00740     uint32_t __addr32 = (uint32_t)(addr); \
00741     uint16_t __result;                  \
00742     __asm__ __volatile__                \
00743     (                                   \
00744         "out %2, %C1"   "\n\t"          \
00745         "mov r31, %B1"  "\n\t"          \
00746         "mov r30, %A1"  "\n\t"          \
00747         "elpm"          "\n\t"          \
00748         "mov %A0, r0"   "\n\t"          \
00749         "in r0, %2"     "\n\t"          \
00750         "adiw r30, 1"   "\n\t"          \
00751         "adc r0, __zero_reg__" "\n\t"   \
00752         "out %2, r0"    "\n\t"          \
00753         "elpm"          "\n\t"          \
00754         "mov %B0, r0"   "\n\t"          \
00755         : "=r" (__result)               \
00756         : "r" (__addr32),               \
00757           "I" (_SFR_IO_ADDR(RAMPZ))     \
00758         : "r0", "r30", "r31"            \
00759     );                                  \
00760     __result;                           \
00761 }))
00762 
00763 #define __ELPM_word_enhanced__(addr)    \
00764 (__extension__({                        \
00765     uint32_t __addr32 = (uint32_t)(addr); \
00766     uint16_t __result;                  \
00767     __asm__ __volatile__                \
00768     (                                   \
00769         "out %2, %C1"   "\n\t"          \
00770         "movw r30, %1"  "\n\t"          \
00771         "elpm %A0, Z+"  "\n\t"          \
00772         "elpm %B0, Z"   "\n\t"          \
00773         : "=r" (__result)               \
00774         : "r" (__addr32),               \
00775           "I" (_SFR_IO_ADDR(RAMPZ))     \
00776         : "r30", "r31"                  \
00777     );                                  \
00778     __result;                           \
00779 }))
00780 
00781 #define __ELPM_word_xmega__(addr)       \
00782 (__extension__({                        \
00783     uint32_t __addr32 = (uint32_t)(addr); \
00784     uint16_t __result;                  \
00785     __asm__ __volatile__                \
00786     (                                   \
00787         "in __tmp_reg__, %2" "\n\t"     \
00788         "out %2, %C1"   "\n\t"          \
00789         "movw r30, %1"  "\n\t"          \
00790         "elpm %A0, Z+"  "\n\t"          \
00791         "elpm %B0, Z"   "\n\t"          \
00792         "out %2, __tmp_reg__"           \
00793         : "=r" (__result)               \
00794         : "r" (__addr32),               \
00795           "I" (_SFR_IO_ADDR(RAMPZ))     \
00796         : "r30", "r31"                  \
00797     );                                  \
00798     __result;                           \
00799 }))
00800 
00801 #define __ELPM_dword_classic__(addr)      \
00802 (__extension__({                          \
00803     uint32_t __addr32 = (uint32_t)(addr); \
00804     uint32_t __result;                    \
00805     __asm__ __volatile__                  \
00806     (                                     \
00807         "out %2, %C1"          "\n\t"     \
00808         "mov r31, %B1"         "\n\t"     \
00809         "mov r30, %A1"         "\n\t"     \
00810         "elpm"                 "\n\t"     \
00811         "mov %A0, r0"          "\n\t"     \
00812         "in r0, %2"            "\n\t"     \
00813         "adiw r30, 1"          "\n\t"     \
00814         "adc r0, __zero_reg__" "\n\t"     \
00815         "out %2, r0"           "\n\t"     \
00816         "elpm"                 "\n\t"     \
00817         "mov %B0, r0"          "\n\t"     \
00818         "in r0, %2"            "\n\t"     \
00819         "adiw r30, 1"          "\n\t"     \
00820         "adc r0, __zero_reg__" "\n\t"     \
00821         "out %2, r0"           "\n\t"     \
00822         "elpm"                 "\n\t"     \
00823         "mov %C0, r0"          "\n\t"     \
00824         "in r0, %2"            "\n\t"     \
00825         "adiw r30, 1"          "\n\t"     \
00826         "adc r0, __zero_reg__" "\n\t"     \
00827         "out %2, r0"           "\n\t"     \
00828         "elpm"                 "\n\t"     \
00829         "mov %D0, r0"          "\n\t"     \
00830         : "=r" (__result)                 \
00831         : "r" (__addr32),                 \
00832           "I" (_SFR_IO_ADDR(RAMPZ))       \
00833         : "r0", "r30", "r31"              \
00834     );                                    \
00835     __result;                             \
00836 }))
00837 
00838 #define __ELPM_dword_enhanced__(addr)     \
00839 (__extension__({                          \
00840     uint32_t __addr32 = (uint32_t)(addr); \
00841     uint32_t __result;                    \
00842     __asm__ __volatile__                  \
00843     (                                     \
00844         "out %2, %C1"   "\n\t"            \
00845         "movw r30, %1"  "\n\t"            \
00846         "elpm %A0, Z+"  "\n\t"            \
00847         "elpm %B0, Z+"  "\n\t"            \
00848         "elpm %C0, Z+"  "\n\t"            \
00849         "elpm %D0, Z"   "\n\t"            \
00850         : "=r" (__result)                 \
00851         : "r" (__addr32),                 \
00852           "I" (_SFR_IO_ADDR(RAMPZ))       \
00853         : "r30", "r31"                    \
00854     );                                    \
00855     __result;                             \
00856 }))
00857 
00858 #define __ELPM_dword_xmega__(addr)        \
00859 (__extension__({                          \
00860     uint32_t __addr32 = (uint32_t)(addr); \
00861     uint32_t __result;                    \
00862     __asm__ __volatile__                  \
00863     (                                     \
00864         "in __tmp_reg__, %2" "\n\t"       \
00865         "out %2, %C1"   "\n\t"            \
00866         "movw r30, %1"  "\n\t"            \
00867         "elpm %A0, Z+"  "\n\t"            \
00868         "elpm %B0, Z+"  "\n\t"            \
00869         "elpm %C0, Z+"  "\n\t"            \
00870         "elpm %D0, Z"   "\n\t"            \
00871         "out %2, __tmp_reg__"             \
00872         : "=r" (__result)                 \
00873         : "r" (__addr32),                 \
00874           "I" (_SFR_IO_ADDR(RAMPZ))       \
00875         : "r30", "r31"                    \
00876     );                                    \
00877     __result;                             \
00878 }))
00879 
00880 #define __ELPM_float_classic__(addr)      \
00881 (__extension__({                          \
00882     uint32_t __addr32 = (uint32_t)(addr); \
00883     float __result;                       \
00884     __asm__ __volatile__                  \
00885     (                                     \
00886         "out %2, %C1"          "\n\t"     \
00887         "mov r31, %B1"         "\n\t"     \
00888         "mov r30, %A1"         "\n\t"     \
00889         "elpm"                 "\n\t"     \
00890         "mov %A0, r0"          "\n\t"     \
00891         "in r0, %2"            "\n\t"     \
00892         "adiw r30, 1"          "\n\t"     \
00893         "adc r0, __zero_reg__" "\n\t"     \
00894         "out %2, r0"           "\n\t"     \
00895         "elpm"                 "\n\t"     \
00896         "mov %B0, r0"          "\n\t"     \
00897         "in r0, %2"            "\n\t"     \
00898         "adiw r30, 1"          "\n\t"     \
00899         "adc r0, __zero_reg__" "\n\t"     \
00900         "out %2, r0"           "\n\t"     \
00901         "elpm"                 "\n\t"     \
00902         "mov %C0, r0"          "\n\t"     \
00903         "in r0, %2"            "\n\t"     \
00904         "adiw r30, 1"          "\n\t"     \
00905         "adc r0, __zero_reg__" "\n\t"     \
00906         "out %2, r0"           "\n\t"     \
00907         "elpm"                 "\n\t"     \
00908         "mov %D0, r0"          "\n\t"     \
00909         : "=r" (__result)                 \
00910         : "r" (__addr32),                 \
00911           "I" (_SFR_IO_ADDR(RAMPZ))       \
00912         : "r0", "r30", "r31"              \
00913     );                                    \
00914     __result;                             \
00915 }))
00916 
00917 #define __ELPM_float_enhanced__(addr)     \
00918 (__extension__({                          \
00919     uint32_t __addr32 = (uint32_t)(addr); \
00920     float __result;                       \
00921     __asm__ __volatile__                  \
00922     (                                     \
00923         "out %2, %C1"   "\n\t"            \
00924         "movw r30, %1"  "\n\t"            \
00925         "elpm %A0, Z+"  "\n\t"            \
00926         "elpm %B0, Z+"  "\n\t"            \
00927         "elpm %C0, Z+"  "\n\t"            \
00928         "elpm %D0, Z"   "\n\t"            \
00929         : "=r" (__result)                 \
00930         : "r" (__addr32),                 \
00931           "I" (_SFR_IO_ADDR(RAMPZ))       \
00932         : "r30", "r31"                    \
00933     );                                    \
00934     __result;                             \
00935 }))
00936 
00937 #define __ELPM_float_xmega__(addr)        \
00938 (__extension__({                          \
00939     uint32_t __addr32 = (uint32_t)(addr); \
00940     float __result;                       \
00941     __asm__ __volatile__                  \
00942     (                                     \
00943         "in __tmp_reg__, %2" "\n\t"       \
00944         "out %2, %C1"   "\n\t"            \
00945         "movw r30, %1"  "\n\t"            \
00946         "elpm %A0, Z+"  "\n\t"            \
00947         "elpm %B0, Z+"  "\n\t"            \
00948         "elpm %C0, Z+"  "\n\t"            \
00949         "elpm %D0, Z"   "\n\t"            \
00950         "out %2, __tmp_reg__"             \
00951         : "=r" (__result)                 \
00952         : "r" (__addr32),                 \
00953           "I" (_SFR_IO_ADDR(RAMPZ))       \
00954         : "r30", "r31"                    \
00955     );                                    \
00956     __result;                             \
00957 }))
00958 
00959 /* 
00960 Check for architectures that implement RAMPD (avrxmega3, avrxmega5, 
00961 avrxmega7) as they need to save/restore RAMPZ for ELPM macros so it does
00962 not interfere with data accesses. 
00963 */
00964 #if defined (__AVR_HAVE_RAMPD__)
00965 
00966 #define __ELPM(addr)        __ELPM_xmega__(addr)
00967 #define __ELPM_word(addr)   __ELPM_word_xmega__(addr)
00968 #define __ELPM_dword(addr)  __ELPM_dword_xmega__(addr)
00969 #define __ELPM_float(addr)  __ELPM_float_xmega__(addr)
00970 
00971 #else
00972 
00973 #if defined (__AVR_HAVE_LPMX__)
00974 
00975 #define __ELPM(addr)        __ELPM_enhanced__(addr)
00976 #define __ELPM_word(addr)   __ELPM_word_enhanced__(addr)
00977 #define __ELPM_dword(addr)  __ELPM_dword_enhanced__(addr)
00978 #define __ELPM_float(addr)  __ELPM_float_enhanced__(addr)
00979 
00980 #else
00981 
00982 #define __ELPM(addr)        __ELPM_classic__(addr)
00983 #define __ELPM_word(addr)   __ELPM_word_classic__(addr)
00984 #define __ELPM_dword(addr)  __ELPM_dword_classic__(addr)
00985 #define __ELPM_float(addr)  __ELPM_float_classic__(addr)
00986 
00987 #endif  /* __AVR_HAVE_LPMX__ */
00988 
00989 #endif  /* __AVR_HAVE_RAMPD__ */
00990 
00991 
00992 /** \ingroup avr_pgmspace
00993     \def pgm_read_byte_far(address_long)
00994     Read a byte from the program space with a 32-bit (far) address. 
00995 
00996     \note The address is a byte address. 
00997     The address is in the program space. */
00998 
00999 #define pgm_read_byte_far(address_long)  __ELPM((uint32_t)(address_long))
01000 
01001 /** \ingroup avr_pgmspace
01002     \def pgm_read_word_far(address_long)
01003     Read a word from the program space with a 32-bit (far) address. 
01004 
01005     \note The address is a byte address.
01006     The address is in the program space. */
01007 
01008 #define pgm_read_word_far(address_long)  __ELPM_word((uint32_t)(address_long))
01009 
01010 /** \ingroup avr_pgmspace
01011     \def pgm_read_dword_far(address_long)
01012     Read a double word from the program space with a 32-bit (far) address. 
01013 
01014     \note The address is a byte address.
01015     The address is in the program space. */
01016 
01017 #define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long))
01018 
01019 /** \ingroup avr_pgmspace
01020     \def pgm_read_float_far(address_long)
01021     Read a float from the program space with a 32-bit (far) address. 
01022 
01023     \note The address is a byte address.
01024     The address is in the program space. */
01025 
01026 #define pgm_read_float_far(address_long) __ELPM_float((uint32_t)(address_long))
01027 
01028 /** \ingroup avr_pgmspace
01029     \def pgm_read_ptr_far(address_long)
01030     Read a pointer from the program space with a 32-bit (far) address. 
01031 
01032     \note The address is a byte address.
01033     The address is in the program space. */
01034 
01035 #define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long))
01036 
01037 #endif /* RAMPZ or __DOXYGEN__ */
01038 
01039 /** \ingroup avr_pgmspace
01040     \def pgm_read_byte(address_short)
01041     Read a byte from the program space with a 16-bit (near) address. 
01042 
01043     \note The address is a byte address. 
01044     The address is in the program space. */
01045 
01046 #define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)
01047 
01048 /** \ingroup avr_pgmspace
01049     \def pgm_read_word(address_short)
01050     Read a word from the program space with a 16-bit (near) address. 
01051 
01052     \note The address is a byte address. 
01053     The address is in the program space. */
01054 
01055 #define pgm_read_word(address_short)    pgm_read_word_near(address_short)
01056 
01057 /** \ingroup avr_pgmspace
01058     \def pgm_read_dword(address_short)
01059     Read a double word from the program space with a 16-bit (near) address. 
01060 
01061     \note The address is a byte address. 
01062     The address is in the program space. */
01063 
01064 #define pgm_read_dword(address_short)   pgm_read_dword_near(address_short)
01065 
01066 /** \ingroup avr_pgmspace
01067     \def pgm_read_float(address_short)
01068     Read a float from the program space with a 16-bit (near) address. 
01069 
01070     \note The address is a byte address. 
01071     The address is in the program space. */
01072 
01073 #define pgm_read_float(address_short)   pgm_read_float_near(address_short)
01074 
01075 /** \ingroup avr_pgmspace
01076     \def pgm_read_ptr(address_short)
01077     Read a pointer from the program space with a 16-bit (near) address. 
01078 
01079     \note The address is a byte address. 
01080     The address is in the program space. */
01081 
01082 #define pgm_read_ptr(address_short)     pgm_read_ptr_near(address_short)
01083 
01084 /* pgm_get_far_address() macro
01085 
01086    This macro facilitates the obtention of a 32 bit "far" pointer (only 24 bits
01087    used) to data even passed the 64KB limit for the 16 bit ordinary pointer. It
01088    is similar to the '&' operator, with some limitations.
01089 
01090    Comments:
01091 
01092    - The overhead is minimal and it's mainly due to the 32 bit size operation.
01093 
01094    - 24 bit sizes guarantees the code compatibility for use in future devices.
01095 
01096    - hh8() is an undocumented feature but seems to give the third significant byte
01097      of a 32 bit data and accepts symbols, complementing the functionality of hi8()
01098      and lo8(). There is not an equivalent assembler function to get the high
01099      significant byte.
01100 
01101    - 'var' has to be resolved at linking time as an existing symbol, i.e, a simple
01102      type variable name, an array name (not an indexed element of the array, if the
01103      index is a constant the compiler does not complain but fails to get the address
01104      if optimization is enabled), a struct name or a struct field name, a function
01105      identifier, a linker defined identifier,...
01106 
01107    - The returned value is the identifier's VMA (virtual memory address) determined
01108      by the linker and falls in the corresponding memory region. The AVR Harvard
01109      architecture requires non overlapping VMA areas for the multiple address spaces
01110      in the processor: Flash ROM, RAM, and EEPROM. Typical offset for this are
01111      0x00000000, 0x00800xx0, and 0x00810000 respectively, derived from the linker
01112          script used and linker options. The value returned can be seen then as a
01113      universal pointer.
01114 
01115 */
01116 
01117 #define pgm_get_far_address(var)                          \
01118 ({                                                    \
01119         uint_farptr_t tmp;                                \
01120                                                       \
01121         __asm__ __volatile__(                             \
01122                                                       \
01123                         "ldi    %A0, lo8(%1)"           "\n\t"    \
01124                         "ldi    %B0, hi8(%1)"           "\n\t"    \
01125                         "ldi    %C0, hh8(%1)"           "\n\t"    \
01126                         "clr    %D0"                    "\n\t"    \
01127                 :                                             \
01128                         "=d" (tmp)                                \
01129                 :                                             \
01130                         "p"  (&(var))                             \
01131         );                                                \
01132         tmp;                                              \
01133 })
01134 
01135 
01136 
01137 extern const void * memchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;
01138 extern int memcmp_P(const void *, const void *, size_t) __ATTR_PURE__;
01139 extern void *memccpy_P(void *, const void *, int __val, size_t);
01140 extern void *memcpy_P(void *, const void *, size_t);
01141 extern void *memmem_P(const void *, size_t, const void *, size_t) __ATTR_PURE__;
01142 extern const void * memrchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;
01143 extern char *strcat_P(char *, const char *);
01144 extern const char * strchr_P(const char *, int __val) __ATTR_CONST__;
01145 extern const char * strchrnul_P(const char *, int __val) __ATTR_CONST__;
01146 extern int strcmp_P(const char *, const char *) __ATTR_PURE__;
01147 extern char *strcpy_P(char *, const char *);
01148 extern int strcasecmp_P(const char *, const char *) __ATTR_PURE__;
01149 extern char *strcasestr_P(const char *, const char *) __ATTR_PURE__;
01150 extern size_t strcspn_P(const char *__s, const char * __reject) __ATTR_PURE__;
01151 extern size_t strlcat_P (char *, const char *, size_t );
01152 extern size_t strlcpy_P (char *, const char *, size_t );
01153 extern size_t __strlen_P(const char *) __ATTR_CONST__;  /* program memory can't change */
01154 extern size_t strnlen_P(const char *, size_t) __ATTR_CONST__; /* program memory can't change */
01155 extern int strncmp_P(const char *, const char *, size_t) __ATTR_PURE__;
01156 extern int strncasecmp_P(const char *, const char *, size_t) __ATTR_PURE__;
01157 extern char *strncat_P(char *, const char *, size_t);
01158 extern char *strncpy_P(char *, const char *, size_t);
01159 extern char *strpbrk_P(const char *__s, const char * __accept) __ATTR_PURE__;
01160 extern const char * strrchr_P(const char *, int __val) __ATTR_CONST__;
01161 extern char *strsep_P(char **__sp, const char * __delim);
01162 extern size_t strspn_P(const char *__s, const char * __accept) __ATTR_PURE__;
01163 extern char *strstr_P(const char *, const char *) __ATTR_PURE__;
01164 extern char *strtok_P(char *__s, const char * __delim);
01165 extern char *strtok_rP(char *__s, const char * __delim, char **__last);
01166 
01167 extern size_t strlen_PF (uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
01168 extern size_t strnlen_PF (uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
01169 extern void *memcpy_PF (void *dest, uint_farptr_t src, size_t len);
01170 extern char *strcpy_PF (char *dest, uint_farptr_t src);
01171 extern char *strncpy_PF (char *dest, uint_farptr_t src, size_t len);
01172 extern char *strcat_PF (char *dest, uint_farptr_t src);
01173 extern size_t strlcat_PF (char *dst, uint_farptr_t src, size_t siz);
01174 extern char *strncat_PF (char *dest, uint_farptr_t src, size_t len);
01175 extern int strcmp_PF (const char *s1, uint_farptr_t s2) __ATTR_PURE__;
01176 extern int strncmp_PF (const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
01177 extern int strcasecmp_PF (const char *s1, uint_farptr_t s2) __ATTR_PURE__;
01178 extern int strncasecmp_PF (const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
01179 extern char *strstr_PF (const char *s1, uint_farptr_t s2);
01180 extern size_t strlcpy_PF (char *dst, uint_farptr_t src, size_t siz);
01181 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
01182 
01183 
01184 __attribute__((__always_inline__)) static inline size_t strlen_P(const char * s);
01185 static inline size_t strlen_P(const char *s) {
01186   return __builtin_constant_p(__builtin_strlen(s))
01187      ? __builtin_strlen(s) : __strlen_P(s);
01188 } 
01189 
01190 
01191 
01192 #ifdef __cplusplus
01193 }
01194 #endif
01195 
01196 #endif /* __PGMSPACE_H_ */

Automatically generated by Doxygen 1.6.1 on 25 Apr 2014.