arduino_ci 0.1.20 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -19
  3. data/REFERENCE.md +625 -0
  4. data/cpp/arduino/Arduino.h +1 -2
  5. data/cpp/arduino/AvrMath.h +117 -17
  6. data/cpp/arduino/Client.h +26 -0
  7. data/cpp/arduino/EEPROM.h +64 -0
  8. data/cpp/arduino/Godmode.cpp +38 -19
  9. data/cpp/arduino/Godmode.h +88 -22
  10. data/cpp/arduino/HardwareSerial.h +9 -28
  11. data/cpp/arduino/IPAddress.h +59 -0
  12. data/cpp/arduino/MockEventQueue.h +86 -0
  13. data/cpp/arduino/PinHistory.h +64 -24
  14. data/cpp/arduino/Print.h +9 -12
  15. data/cpp/arduino/Printable.h +8 -0
  16. data/cpp/arduino/SPI.h +11 -3
  17. data/cpp/arduino/Server.h +5 -0
  18. data/cpp/arduino/Udp.h +27 -0
  19. data/cpp/arduino/Wire.h +234 -0
  20. data/cpp/arduino/avr/io.h +10 -1
  21. data/cpp/arduino/avr/pgmspace.h +76 -46
  22. data/cpp/arduino/ci/StreamTape.h +36 -0
  23. data/cpp/unittest/ArduinoUnitTests.h +1 -0
  24. data/cpp/unittest/Compare.h +91 -897
  25. data/cpp/unittest/OstreamHelpers.h +9 -0
  26. data/exe/arduino_ci.rb +401 -0
  27. data/exe/arduino_ci_remote.rb +2 -385
  28. data/lib/arduino_ci.rb +1 -0
  29. data/lib/arduino_ci/arduino_cmd.rb +13 -9
  30. data/lib/arduino_ci/arduino_downloader.rb +5 -4
  31. data/lib/arduino_ci/arduino_installation.rb +5 -5
  32. data/lib/arduino_ci/ci_config.rb +12 -0
  33. data/lib/arduino_ci/cpp_library.rb +152 -25
  34. data/lib/arduino_ci/installed_cpp_library.rb +0 -0
  35. data/lib/arduino_ci/library_properties.rb +86 -0
  36. data/lib/arduino_ci/version.rb +1 -1
  37. data/misc/default.yml +50 -3
  38. metadata +23 -13
  39. data/cpp/arduino/Arduino.h.orig +0 -143
  40. data/cpp/arduino/Nullptr.h +0 -7
  41. data/cpp/arduino/ci/Queue.h +0 -73
  42. data/exe/libasan.rb +0 -29
@@ -40,7 +40,11 @@
40
40
 
41
41
  class SPISettings {
42
42
  public:
43
- SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode){};
43
+ uint8_t bitOrder;
44
+
45
+ SPISettings(uint32_t clock, uint8_t bitOrder = MSBFIRST, uint8_t dataMode = SPI_MODE0) {
46
+ this->bitOrder = bitOrder;
47
+ };
44
48
  SPISettings(){};
45
49
  };
46
50
 
@@ -68,6 +72,7 @@ public:
68
72
  // and configure the correct settings.
69
73
  void beginTransaction(SPISettings settings)
70
74
  {
75
+ this->bitOrder = settings.bitOrder;
71
76
  #ifdef SPI_TRANSACTION_MISMATCH_LED
72
77
  if (inTransactionFlag) {
73
78
  pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
@@ -94,10 +99,12 @@ public:
94
99
  uint16_t transfer16(uint16_t data) {
95
100
  union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
96
101
  in.val = data;
97
- if (!(SPCR & (1 << DORD))) {
102
+ if (bitOrder == MSBFIRST) {
98
103
  out.msb = transfer(in.msb);
99
104
  out.lsb = transfer(in.lsb);
100
- } else {
105
+ }
106
+ else
107
+ {
101
108
  out.lsb = transfer(in.lsb);
102
109
  out.msb = transfer(in.msb);
103
110
  }
@@ -143,6 +150,7 @@ private:
143
150
  #endif
144
151
 
145
152
  bool isStarted = false;
153
+ uint8_t bitOrder;
146
154
  String* dataIn;
147
155
  String* dataOut;
148
156
  };
@@ -0,0 +1,5 @@
1
+ #pragma once
2
+
3
+ #include <Stream.h>
4
+
5
+ class Server : public Print {};
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include <IPAddress.h>
4
+ #include <Stream.h>
5
+
6
+ class UDP : public Stream {
7
+ protected:
8
+ uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); };
9
+
10
+ public:
11
+ UDP() {
12
+ // The Stream mock defines a String buffer but never puts anyting in it!
13
+ if (!mGodmodeDataIn) {
14
+ mGodmodeDataIn = new String;
15
+ }
16
+ }
17
+ ~UDP() {
18
+ if (mGodmodeDataIn) {
19
+ delete mGodmodeDataIn;
20
+ mGodmodeDataIn = nullptr;
21
+ }
22
+ }
23
+ virtual size_t write(uint8_t value) {
24
+ mGodmodeDataIn->concat(value);
25
+ return 1;
26
+ }
27
+ };
@@ -0,0 +1,234 @@
1
+ /*
2
+ * The Wire Library (https://www.arduino.cc/en/Reference/Wire)
3
+ * allows you to communicate with I2C/TWI devices. The general
4
+ * TWI protocol supports one "master" device and many "slave"
5
+ * devices that share the same two wires (SDA and SCL for data
6
+ * and clock respectively).
7
+ *
8
+ * You initialize the library by calling begin() as a master or
9
+ * begin(myAddress) as a slave (with an int from 8-127). In the
10
+ * initial mock implementation we support only the master role.
11
+ *
12
+ * To send bytes from a master to a slave, start with
13
+ * beginTransmission(slaveAddress), then use write(byte) to
14
+ * enqueue data, and finish with endTransmission().
15
+ *
16
+ * When a master wants to read, it starts with a call to
17
+ * requestFrom(slaveAddress, quantity) which blocks until the
18
+ * request finishes. The return value is either 0 (if the slave
19
+ * does not respond) or the number of bytes requested (which
20
+ * might be more than the number sent since reading is simply
21
+ * looking at a pin value at each clock tick).
22
+ *
23
+ * A master can write to or read from two or more slaves in
24
+ * quick succession (say, during one loop() function), so our
25
+ * mock needs to support preloading data to be read from multiple
26
+ * slaves and archive data sent to multiple slaves.
27
+ *
28
+ * In the mock, this is handled by having an array of wireData_t
29
+ * structures, each of which contains a deque for input and a
30
+ * deque for output. You can preload data to be read and you can
31
+ * look at a log of data that has been written.
32
+ */
33
+
34
+ #pragma once
35
+
36
+ #include <inttypes.h>
37
+ #include "Stream.h"
38
+ #include <cassert>
39
+ #include <deque>
40
+ using std::deque;
41
+
42
+ const size_t SLAVE_COUNT = 128;
43
+ const size_t BUFFER_LENGTH = 32;
44
+
45
+ struct wireData_t {
46
+ uint8_t misoSize; // bytes remaining for this read
47
+ uint8_t mosiSize; // bytes included in this write
48
+ deque<uint8_t> misoBuffer; // master in, slave out
49
+ deque<uint8_t> mosiBuffer; // master out, slave in
50
+ };
51
+
52
+ // Some inspiration taken from
53
+ // https://github.com/arduino/ArduinoCore-megaavr/blob/d2a81093ba66d22dbda14c30d146c231c5910734/libraries/Wire/src/Wire.cpp
54
+ class TwoWire : public ObservableDataStream {
55
+ private:
56
+ bool _didBegin = false;
57
+ wireData_t *in = nullptr; // pointer to current slave for writing
58
+ wireData_t *out = nullptr; // pointer to current slave for reading
59
+ wireData_t slaves[SLAVE_COUNT];
60
+
61
+ public:
62
+ // constructor initializes internal data
63
+ TwoWire() {
64
+ for (int i = 0; i < SLAVE_COUNT; ++i) {
65
+ slaves[i].misoSize = 0;
66
+ slaves[i].mosiSize = 0;
67
+ }
68
+ }
69
+
70
+ // https://www.arduino.cc/en/Reference/WireBegin
71
+ // Initiate the Wire library and join the I2C bus as a master or slave. This
72
+ // should normally be called only once.
73
+ void begin() { begin(0); }
74
+ void begin(uint8_t address) {
75
+ assert(address == 0);
76
+ _didBegin = true;
77
+ }
78
+ void begin(int address) { begin((uint8_t)address); }
79
+ // NOTE: end() is not part of the published API so we ignore it
80
+ void end() {}
81
+
82
+ // https://www.arduino.cc/en/Reference/WireSetClock
83
+ // This function modifies the clock frequency for I2C communication. I2C slave
84
+ // devices have no minimum working clock frequency, however 100KHz is usually
85
+ // the baseline.
86
+ // Since the mock does not actually write pins we ignore this.
87
+ void setClock(uint32_t clock) {}
88
+
89
+ // https://www.arduino.cc/en/Reference/WireBeginTransmission
90
+ // Begin a transmission to the I2C slave device with the given address.
91
+ // Subsequently, queue bytes for transmission with the write() function and
92
+ // transmit them by calling endTransmission().
93
+ // For the mock we update our output to the proper destination.
94
+ void beginTransmission(uint8_t address) {
95
+ assert(_didBegin);
96
+ assert(address > 0 && address < SLAVE_COUNT);
97
+ assert(out == nullptr);
98
+ out = &slaves[address];
99
+ out->mosiSize = 0;
100
+ }
101
+ void beginTransmission(int address) { beginTransmission((uint8_t)address); }
102
+
103
+ // https://www.arduino.cc/en/Reference/WireEndTransmission
104
+ // Ends a transmission to a slave device that was begun by beginTransmission()
105
+ // and transmits the bytes that were queued by write().
106
+ // In the mock we just leave the bytes there in the buffer
107
+ // to be read by the testing API and we ignore the sendStop.
108
+ uint8_t endTransmission(bool sendStop) {
109
+ assert(_didBegin);
110
+ assert(out);
111
+ out = nullptr;
112
+ return 0; // success
113
+ }
114
+ uint8_t endTransmission(void) { return endTransmission(true); }
115
+
116
+ // https://www.arduino.cc/en/Reference/WireRequestFrom
117
+ // Used by the master to request bytes from a slave device. The bytes may then
118
+ // be retrieved with the available() and read() functions.
119
+ uint8_t requestFrom(uint8_t address, uint8_t quantity, uint32_t _iaddress, uint8_t _isize, uint8_t stop) {
120
+ assert(_didBegin);
121
+ assert(address > 0 && address < SLAVE_COUNT);
122
+ assert(quantity <= BUFFER_LENGTH);
123
+ in = &slaves[address];
124
+ // do we have enough data in the input buffer
125
+ if (quantity <= (in->misoBuffer).size()) { // enough data
126
+ in->misoSize = quantity;
127
+ return quantity;
128
+ } else { // not enough data
129
+ in->misoSize = 0;
130
+ in = nullptr;
131
+ return 0;
132
+ }
133
+ }
134
+
135
+ uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t stop) {
136
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint32_t)0, (uint8_t)0, (uint8_t)stop);
137
+ }
138
+
139
+ uint8_t requestFrom(uint8_t address, uint8_t quantity) {
140
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
141
+ }
142
+
143
+ uint8_t requestFrom(int address, int quantity) {
144
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true);
145
+ }
146
+ uint8_t requestFrom(int address, int quantity, int stop) {
147
+ return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)stop);
148
+ }
149
+
150
+ // https://www.arduino.cc/en/Reference/WireWrite
151
+ // Writes data from a slave device in response to a request from a master, or
152
+ // queues bytes for transmission from a master to slave device (in-between
153
+ // calls to beginTransmission() and endTransmission()).
154
+ size_t write(uint8_t value) {
155
+ assert(out);
156
+ assert(++(out->mosiSize) <= BUFFER_LENGTH);
157
+ (out->mosiBuffer).push_back(value);
158
+ return 1; // number of bytes written
159
+ }
160
+ size_t write(const char *str) {
161
+ return str == NULL ? 0 : write((const uint8_t *)str, String(str).length());
162
+ }
163
+ size_t write(const uint8_t *buffer, size_t size) {
164
+ size_t n;
165
+ for (n = 0; size && write(*buffer++) && ++n; --size)
166
+ ;
167
+ return n;
168
+ }
169
+ size_t write(const char *buffer, size_t size) {
170
+ return write((const uint8_t *)buffer, size);
171
+ }
172
+ size_t write(unsigned long n) { return write((uint8_t)n); }
173
+ size_t write(long n) { return write((uint8_t)n); }
174
+ size_t write(unsigned int n) { return write((uint8_t)n); }
175
+ size_t write(int n) { return write((uint8_t)n); }
176
+
177
+ // https://www.arduino.cc/en/Reference/WireAvailable
178
+ // Returns the number of bytes available for retrieval with read(). This
179
+ // should be called on a master device after a call to requestFrom() or on a
180
+ // slave inside the onReceive() handler.
181
+ int available(void) {
182
+ assert(in);
183
+ return in->misoSize;
184
+ }
185
+
186
+ // https://www.arduino.cc/en/Reference/WireRead
187
+ // Reads a byte that was transmitted from a slave device to a master after a
188
+ // call to requestFrom() or was transmitted from a master to a slave. read()
189
+ // inherits from the Stream utility class.
190
+ // In the mock we simply return the next byte from the input buffer.
191
+ uint8_t read(void) {
192
+ uint8_t value = peek();
193
+ --in->misoSize;
194
+ in->misoBuffer.pop_front();
195
+ return value; // The next byte received
196
+ }
197
+
198
+ // part of the Stream API
199
+ uint8_t peek(void) {
200
+ assert(in);
201
+ assert(0 < in->misoSize);
202
+ return in->misoBuffer.front(); // The next byte received
203
+ }
204
+
205
+ // part of the Stream API
206
+ void flush(void) {
207
+ // NOTE: commented out in the megaavr repository
208
+ // data already at the (mock) destination
209
+ }
210
+
211
+ // https://www.arduino.cc/en/Reference/WireOnReceive
212
+ // Registers a function to be called when a slave device receives a
213
+ // transmission from a master.
214
+ // We don't (yet) support the slave role in the mock
215
+ void onReceive(void (*callback)(int)) { assert(false); }
216
+
217
+ // https://www.arduino.cc/en/Reference/WireOnRequest
218
+ // Register a function to be called when a master requests data from this
219
+ // slave device.
220
+ // We don't (yet) support the slave role in the mock
221
+ void onRequest(void (*callback)(void)) { assert(false); }
222
+
223
+ // testing methods
224
+ bool didBegin() { return _didBegin; }
225
+
226
+ deque<uint8_t> *getMiso(uint8_t address) {
227
+ return &slaves[address].misoBuffer;
228
+ }
229
+ deque<uint8_t> *getMosi(uint8_t address) {
230
+ return &slaves[address].mosiBuffer;
231
+ }
232
+ };
233
+
234
+ extern TwoWire Wire;
@@ -96,7 +96,16 @@
96
96
  #ifndef _AVR_IO_H_
97
97
  #define _AVR_IO_H_
98
98
 
99
- #define _SFR_IO8(io_addr) (io_addr) // this macro is all we need from the sfr file
99
+ #include <stdint.h>
100
+
101
+ // hardware mocks
102
+ // this set of macros is all we need from the sfr file
103
+ extern volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024];
104
+ #define _SFR_IO8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
105
+ #define _SFR_IO16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
106
+ #define _SFR_MEM8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
107
+ #define _SFR_MEM16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
108
+ #define _SFR_MEM32(io_addr) (*(volatile uint32_t *)(__ARDUINO_CI_SFR_MOCK + io_addr))
100
109
 
101
110
  #if defined (__AVR_AT94K__)
102
111
  # include "ioat94k.h"
@@ -14,8 +14,10 @@ out = externs.map {|l| l.split("(")[0].split(" ")[-1].gsub("*", "") }.uniq
14
14
  out.each { |l| puts d(l) }
15
15
  */
16
16
 
17
- #include <avr/io.h>
18
17
  #include <string.h>
18
+ #include <stdio.h>
19
+ #include <stdint.h>
20
+ #include <stdarg.h>
19
21
 
20
22
  #define PROGMEM
21
23
 
@@ -27,6 +29,11 @@ out.each { |l| puts d(l) }
27
29
  #define PGM_VOID_P const void *
28
30
  #endif
29
31
 
32
+ // These are normally 32-bit, but here use (u)intptr_t to ensure a pointer can
33
+ // always be safely cast to these types.
34
+ typedef intptr_t int_farptr_t;
35
+ typedef uintptr_t uint_farptr_t;
36
+
30
37
  // everything's a no-op
31
38
  #define PSTR(s) ((const char *)(s))
32
39
 
@@ -34,13 +41,13 @@ out.each { |l| puts d(l) }
34
41
  #define pgm_read_word_near(address_short) (* (const uint16_t *) (address_short) )
35
42
  #define pgm_read_dword_near(address_short) (* (const uint32_t *) (address_short) )
36
43
  #define pgm_read_float_near(address_short) (* (const float *) (address_short) )
37
- #define pgm_read_ptr_near(address_short) (* (const void *) (address_short) )
44
+ #define pgm_read_ptr_near(address_short) (* (const void **) (address_short) )
38
45
 
39
46
  #define pgm_read_byte_far(address_long) (* (const uint8_t *) (address_long) )
40
47
  #define pgm_read_word_far(address_long) (* (const uint16_t *) (address_long) )
41
48
  #define pgm_read_dword_far(address_long) (* (const uint32_t *) (address_long) )
42
49
  #define pgm_read_float_far(address_long) (* (const float *) (address_long) )
43
- #define pgm_read_ptr_far(address_long) (* (const void *) (address_long) )
50
+ #define pgm_read_ptr_far(address_long) (* (const void **) (address_long) )
44
51
 
45
52
  #define pgm_read_byte(address_short) pgm_read_byte_near(address_short)
46
53
  #define pgm_read_word(address_short) pgm_read_word_near(address_short)
@@ -50,46 +57,69 @@ out.each { |l| puts d(l) }
50
57
 
51
58
  #define pgm_get_far_address(var) ( (uint_farptr_t) (&(var)) )
52
59
 
53
- #define memchr_P(...) ::memchr(__VA_ARGS__)
54
- #define memcmp_P(...) ::memcmp(__VA_ARGS__)
55
- #define memccpy_P(...) ::memccpy(__VA_ARGS__)
56
- #define memcpy_P(...) ::memcpy(__VA_ARGS__)
57
- #define memmem_P(...) ::memmem(__VA_ARGS__)
58
- #define memrchr_P(...) ::memrchr(__VA_ARGS__)
59
- #define strcat_P(...) ::strcat(__VA_ARGS__)
60
- #define strchr_P(...) ::strchr(__VA_ARGS__)
61
- #define strchrnul_P(...) ::strchrnul(__VA_ARGS__)
62
- #define strcmp_P(...) ::strcmp(__VA_ARGS__)
63
- #define strcpy_P(...) ::strcpy(__VA_ARGS__)
64
- #define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__)
65
- #define strcasestr_P(...) ::strcasestr(__VA_ARGS__)
66
- #define strcspn_P(...) ::strcspn(__VA_ARGS__)
67
- #define strlcat_P(...) ::strlcat(__VA_ARGS__)
68
- #define strlcpy_P(...) ::strlcpy(__VA_ARGS__)
69
- #define strnlen_P(...) ::strnlen(__VA_ARGS__)
70
- #define strncmp_P(...) ::strncmp(__VA_ARGS__)
71
- #define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__)
72
- #define strncat_P(...) ::strncat(__VA_ARGS__)
73
- #define strncpy_P(...) ::strncpy(__VA_ARGS__)
74
- #define strpbrk_P(...) ::strpbrk(__VA_ARGS__)
75
- #define strrchr_P(...) ::strrchr(__VA_ARGS__)
76
- #define strsep_P(...) ::strsep(__VA_ARGS__)
77
- #define strspn_P(...) ::strspn(__VA_ARGS__)
78
- #define strstr_P(...) ::strstr(__VA_ARGS__)
79
- #define strtok_P(...) ::strtok(__VA_ARGS__)
80
- #define strtok_P(...) ::strtok(__VA_ARGS__)
81
- #define strlen_P(...) ::strlen(__VA_ARGS__)
82
- #define strnlen_P(...) ::strnlen(__VA_ARGS__)
83
- #define memcpy_P(...) ::memcpy(__VA_ARGS__)
84
- #define strcpy_P(...) ::strcpy(__VA_ARGS__)
85
- #define strncpy_P(...) ::strncpy(__VA_ARGS__)
86
- #define strcat_P(...) ::strcat(__VA_ARGS__)
87
- #define strlcat_P(...) ::strlcat(__VA_ARGS__)
88
- #define strncat_P(...) ::strncat(__VA_ARGS__)
89
- #define strcmp_P(...) ::strcmp(__VA_ARGS__)
90
- #define strncmp_P(...) ::strncmp(__VA_ARGS__)
91
- #define strcasecmp_P(...) ::strcasecmp(__VA_ARGS__)
92
- #define strncasecmp_P(...) ::strncasecmp(__VA_ARGS__)
93
- #define strstr_P(...) ::strstr(__VA_ARGS__)
94
- #define strlcpy_P(...) ::strlcpy(__VA_ARGS__)
95
- #define memcmp_P(...) ::memcmp(__VA_ARGS__)
60
+ inline const void * memchr_P(const void *s, int val, size_t len) { return memchr(s, val, len); }
61
+ inline int memcmp_P(const void *s1, const void *s2, size_t len) { return memcmp(s1, s2, len); }
62
+ inline void *memcpy_P(void *dest, const void *src, size_t n) { return memcpy(dest, src, n); }
63
+ inline char *strcat_P(char *dest, const char *src) { return strcat(dest, src); }
64
+ inline const char *strchr_P(const char *s, int val) { return strchr(s, val); }
65
+ inline int strcmp_P(const char *s1, const char *s2) { return strcmp(s1, s2); }
66
+ inline char *strcpy_P(char *dest, const char *src) { return strcpy(dest, src); }
67
+ inline size_t strcspn_P(const char *s, const char *reject) { return strcspn(s, reject); }
68
+ // strlcat and strlcpy are AVR-specific and not entirely trivial to reimplement using strncat it seems
69
+ //inline size_t strlcat_P(char *dst, const char *src, size_t siz) { return strlcat(dst, src, siz); }
70
+ //inline size_t strlcpy_P(char *dst, const char *src, size_t siz) { return strlcpy(dst, src, siz); }
71
+ //inline size_t strlcat_PF(char *dst, uint_farptr_t src, size_t n) { return strlcat(dst, (const char*)src, n); }
72
+ //inline size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) { return strlcpy(dst, (const char*)src, siz); }
73
+ inline int strncmp_P(const char *s1, const char *s2, size_t n) { return strncmp(s1, s2, n); }
74
+ inline char *strncat_P(char *dest, const char *src, size_t len) { return strncat(dest, src, len); }
75
+ inline char *strncpy_P(char *dest, const char *src, size_t n) { return strncpy(dest, src, n); }
76
+ inline char *strpbrk_P(const char *s, const char *accept) { return (char*)strpbrk(s, accept); }
77
+ inline const char *strrchr_P(const char *s, int val) { return strrchr(s, val); }
78
+ inline size_t strspn_P(const char *s, const char *accept) { return strspn(s, accept); }
79
+ inline char *strstr_P(const char *s1, const char *s2) { return (char*)strstr(s1, s2); }
80
+ inline char *strtok_P(char *s, const char * delim) { return strtok(s, delim); }
81
+ inline size_t strlen_PF(uint_farptr_t s) { return strlen((char*)s); }
82
+ inline void *memcpy_PF(void *dest, uint_farptr_t src, size_t n) { return memcpy(dest, (const char*)src, n); }
83
+ inline char *strcpy_PF(char *dst, uint_farptr_t src) { return strcpy(dst, (const char*)src); }
84
+ inline char *strncpy_PF(char *dst, uint_farptr_t src, size_t n) { return strncpy(dst, (const char*)src, n); }
85
+ inline char *strcat_PF(char *dst, uint_farptr_t src) { return strcat(dst, (const char*)src); }
86
+ inline char *strncat_PF(char *dst, uint_farptr_t src, size_t n) { return strncat(dst, (const char*)src, n); }
87
+ inline int strcmp_PF(const char *s1, uint_farptr_t s2) { return strcmp(s1, (const char*)s2); }
88
+ inline int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncmp(s1, (const char*)s2, n); }
89
+ inline char *strstr_PF(const char *s1, uint_farptr_t s2) { return (char*)strstr(s1, (const char*)s2); }
90
+ inline int memcmp_PF(const void *s1, uint_farptr_t s2, size_t len) { return memcmp(s1, (const char*)s2, len); }
91
+ inline size_t strlen_P(const char *src) { return strlen(src); }
92
+
93
+ // TODO: These functions cannot be found on the CYGWIN test build for
94
+ // some reason, so disable them for now. Most of these are less common
95
+ // and/or GNU-specific addons anyway
96
+ //inline void *memccpy_P(void *dest, const void *src, int val, size_t len) { return memccpy(dest, src, val, len); }
97
+ //inline void *memmem_P(const void *s1, size_t len1, const void *s2, size_t len2) { return memmem(s1, len1, s2, len2); }
98
+ //inline const void *memrchr_P(const void *src, int val, size_t len) { return memrchr(src, val, len); }
99
+ //inline const char *strchrnul_P(const char *s, int c) { return strchrnul(s, c); }
100
+ //inline int strcasecmp_P(const char *s1, const char *s2) { return strcasecmp(s1, s2); }
101
+ //inline char *strcasestr_P(const char *s1, const char *s2) { return (char*)strcasestr(s1, s2); }
102
+ //inline int strncasecmp_P(const char *s1, const char *s2, size_t n) { return strncasecmp(s1, s2, n); }
103
+ //inline char *strsep_P(char **sp, const char *delim) { return strsep(sp, delim); }
104
+ //inline char *strtok_r_P(char *string, const char *delim, char **last) { return strtok_r(string, delim, last); }
105
+ //inline int strcasecmp_PF(const char *s1, uint_farptr_t s2) { return strcasecmp(s1, (const char*)s2); }
106
+ //inline int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) { return strncasecmp(s1, (const char*)s2, n); }
107
+ //inline size_t strnlen_P(uint_farptr_t s, size_t len) { return strnlen((char*)s, len); }
108
+
109
+ // These are normally defined by stdio.h on AVR, but we cannot override that
110
+ // include file (at least not without no longer being able to include the
111
+ // original as well), so just define these here. It seems likely that any
112
+ // sketch that uses these progmem-stdio functions will also include pgmspace.h
113
+ inline int vfprintf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfprintf(stream, __fmt, __ap); }
114
+ inline int printf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vprintf(__fmt, args); va_end(args); }
115
+ inline int sprintf_P(char *s, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return sprintf(s, __fmt, args); va_end(args); }
116
+ inline int snprintf_P(char *s, size_t __n, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsnprintf(s, __n, __fmt, args); va_end(args); }
117
+ inline int vsprintf_P(char *s, const char *__fmt, va_list ap) { return vsprintf(s, __fmt, ap); }
118
+ inline int vsnprintf_P(char *s, size_t __n, const char *__fmt, va_list ap) { return vsnprintf(s, __n, __fmt, ap); }
119
+ inline int fprintf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfprintf(stream, __fmt, args); va_end(args); }
120
+ inline int fputs_P(const char *str, FILE *__stream) { return fputs(str, __stream); }
121
+ inline int puts_P(const char *str) { return puts(str); }
122
+ inline int vfscanf_P(FILE *stream, const char *__fmt, va_list __ap) { return vfscanf(stream, __fmt, __ap); }
123
+ inline int fscanf_P(FILE *stream, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vfscanf(stream, __fmt, args); va_end(args); }
124
+ inline int scanf_P(const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vscanf(__fmt, args); va_end(args); }
125
+ inline int sscanf_P(const char *buf, const char *__fmt, ...) { va_list args; va_start(args, __fmt); return vsscanf(buf, __fmt, args); va_end(args); }