ESP8266 ILI9341 display support code with printf sources, wire-frame viewer and custom fonts  1.0
ESP8266ILI9341DisplayProject
printf.c
Go to the documentation of this file.
1 
28 #ifdef USER_CONFIG
29 #include "user_config.h"
30 #else
31 //#include <stdio.h>
32 #endif
33 
34 #include <stdint.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <math.h>
38 
39 #include "mathio.h"
40 
41 // =============================================
42 
43 // Below we included functions that are defined elsewhere
44 // They are included within printf to allow this to be standalone
45 // This is done by looking at header defines for the time being
46 
51 size_t
53 strlen(const char *str)
54 {
55  int len=0;
56  // String length
57  while(*str++)
58  ++len;
59  return(len);
60 }
61 
62 // Skip if we have linux ctype.h
66 #undef isdigit
67 MEMSPACE
68 int
70 isdigit(int c)
71 {
72  if(c >= '0' && c <= '9')
73  return(1);
74  return(0);
75 }
76 
77 // =============================================
78 // start of support functions
79 // =============================================
80 
85 MEMSPACE
86 void
88 reverse(char *str)
89 {
90  char temp;
91  int i;
92  int len = strlen(str);
93  // Reverse
94  // We only exchange up to half way
95  for (i = 0; i < (len >> 1); i++)
96  {
97  temp = str[len - i - 1];
98  str[len - i - 1] = str[i];
99  str[i] = temp;
100  }
101 }
102 
106 MEMSPACE
107 void
108 WEAK_ATR
109 strupper(char *str)
110 {
111  while(*str)
112  {
113  if(*str >= 'a' && *str <= 'z')
114  *str -= ( 'a' - 'A');
115  ++str;
116  }
117 }
118 
119 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
120 #error bin2num ASSUME little endian
121 #endif
122 
138 MEMSPACE
139 int bin2num(uint8_t *str, int strmax, int nummin, int base, uint8_t *nump, int numsize, int sign_ch)
140 {
141  int i,j,carry;
142  uint8_t data;
143 
144  int numbits = numsize * 8;
145 
146  for(i=0;i<=nummin;++i)
147  str[i] = 0; // initial string starts out empty
148 
149  // FIXME Little/Big-endian
150  // Loop for all bits (numsize in total) in the binary number (bin)
151  // Examine each bit MSB to LSB order
152  for(i = numbits - 1; i>= 0; --i)
153  {
154  // We extract 1 bit at a time from the binary number (MSB to LSB order)
155  // FIXME Little/Big-endian
156  data = nump[i>>3];
157  // If extracted bit was set carry = 1, else 0
158  // FIXME Little/Big-endian
159  carry = ( data & (1 << (i & 7)) ) ? 1 : 0;
160 
161  // Multiply base number by two and add the previously extracted bit
162  // Next do base digit to digit carries as needed
163  // Note: nummin is the current string size that can grow as needed
164  // Carry test in the loop can optionally extend base strings size
165  for(j=0;(j<nummin || carry) ;++j)
166  {
167  if(j >= (strmax - 2))
168  break;
169 
170  data = str[j];
171  data = (data<<1) | carry;
172  // process base carry
173  carry = 0;
174  if(data >= base)
175  {
176  data -= base;
177  carry = 1;
178  }
179  str[j] = data;
180  }
181  str[j] = 0; // zero next digit if carry extends size
182  nummin = j; // update nummin if carry extends size
183  }
184 
185  // Add ASCII '0' or 'a' offsets to base string
186  for(i=0;i<nummin;++i)
187  {
188  if(str[i] < 10)
189  str[i] += '0';
190  else str[i] += 'a'-10;
191  }
192 
193  // Add optional sign character
194  if(sign_ch && i <= (strmax - 2))
195  {
196  str[i++] = sign_ch;
197  ++nummin;
198  }
199  str[i] = 0; // Terminate string eith EOS
200 
201  reverse((char *)str); // Reverse in place to correct order
202 
203  return(nummin); // Return string size
204 }
205 
206 // =============================================
208 typedef struct {
209  char *str;
210  int ind;
211  int max;
212 } p_ch_t;
213 
216 
221 MEMSPACE
222 void pch_init(char *str, int max)
223 {
224  _pch.str = str;
225  _pch.ind = 0;
226  _pch.max = max-1;
227  _pch.str[0] = 0;
228 }
229 
230 
236 MEMSPACE
237 int pch(char ch)
238 {
239  // Add the character while ther is room
240  if(_pch.ind < _pch.max)
241  _pch.str[_pch.ind++] = ch;
242  else
243  _pch.str[_pch.ind] = 0; // Add EOS when limit exceeded
244  return(_pch.ind);
245 }
246 
249 MEMSPACE
250 int pch_ind()
251 {
252  return(_pch.ind);
253 }
254 
257 MEMSPACE
259 {
260  return(_pch.max);
261 }
262 
263 // =============================================
264 // end of support functions
265 // =============================================
269 MEMSPACE
271 {
272  if(f.b.left)
273  printf("left flag\n");
274  if(f.b.plus)
275  printf("plus flag\n");
276  if(f.b.space)
277  printf("space flag\n");
278  if(f.b.zero)
279  printf("zero flag\n");
280  if(f.b.alt)
281  printf("alt flag\n");
282  if(f.b.width)
283  printf("width flag\n");
284  if(f.b.prec)
285  printf("prec flag\n");
286  if(f.b.neg)
287  printf("< 0 flag\n");
288 }
289 
312 
313 MEMSPACE
314 int p_ntoa(uint8_t *nump, int numsize, char *str, int strmax, int radix, int width, int prec, f_t f)
315 {
316  unsigned int sign_ch;
317  int ind;
318  int digits;
319 
320  digits = 0;
321 
322  // Unsigned, hex,octal,binary should leave these flasg zero
323  //f.b.space = 0;
324  //f.b.plus = 0;
325  //f.b.neg = 0;
326 
327  sign_ch = 0;
328  if(f.b.neg)
329  sign_ch = '-';
330  else if(f.b.plus)
331  sign_ch = '+';
332  else if(f.b.space)
333  sign_ch = ' ';
334 
335 //print_flags(f);
336 
337  /* Some Combinations of flags are not permitted
338  * - or impact the interpretation of others */
339  if(f.b.zero)
340  {
341  // 0 disabled if precision or left align
342  if(f.b.left || f.b.prec)
343  f.b.zero = 0;
344  }
345 
346 
347  if(f.b.prec)
348  digits = prec;
349 
350  if(!f.b.width && !f.b.prec)
351  digits = 1; // at least one digit
352 
353  if(f.b.width)
354  {
355  if(!f.b.zero)
356  {
357  // Width and no leading zeros require at least one digit
358  if(!f.b.prec)
359  digits = 1; // at least one digit
360  }
361  else /* precision and 0 can not occur together - previously tested */
362  {
363  digits = width;
364  /* make room for a sign ? */
365  if(f.b.plus || f.b.neg || f.b.space)
366  --digits;
367  }
368  }
369  ind = bin2num((uint8_t *)str, strmax, digits, radix, nump, numsize, sign_ch);
370  return(ind);
371 }
372 
373 
374 #ifdef FLOATIO
375 MEMSPACE
383 int p_ftoa(double val, char *str, int max, int width, int prec, f_t f)
384 {
385 
386  char *save = str;
387  double fscale;
388  int idigits, digits;
389  int digit;
390 
391  pch_init(str,max);
392 
393 /*
394 FIXME
395 Notice rounding - testing will be tricky
396 ERROR: [% 15.1f], [-10252956608208.250000]
397  G[-10252956608208.2]
398  B[-10252956608208.3]
399  error:9.90567929632045986708e-15
400 
401 */
402 //printf("val:%.20e\n", val);
403 //print_flags(f);
404  if(val < 0.0)
405  {
406  val = -val;
407  f.b.neg = 1;
408  }
409  if(f.b.neg)
410  pch('-');
411  else if(f.b.plus)
412  pch('+');
413  else if(f.b.space)
414  pch(' ');
415 
416  // prec only applies to fractional digits
417  if(prec < 0)
418  prec = 0;
419 
420  // NOTE: prec is anchored at the decimal point
421 
422  fscale = 0.0;
423  idigits = 1; // number of integer digits
424  if(val) // if zero no rounding needed
425  {
426  // do rounding - IF precision specified
427  // number of fractional digits to display
428  fscale = 0.5; // rounding value if prec = 0
429  if(f.b.prec)
430  {
431  digits = prec;
432  while(digits > 0)
433  {
434  fscale /= 10.0; // adjust rounding value
435  --digits;
436  }
437  }
438 //printf("val;:%.20e, fscale:%.20e\n", val, fscale);
439  val += fscale; // round to prec
440 
441  while(val >= 10.0)
442  {
443  ++idigits;
444  val /= 10.0;
445  }
446  // So we know that fval < 1.0;
447  }
448 
449 //printf("idigits:%d\n",idigits);
450 
451  if(f.b.zero && !f.b.left)
452  {
453  if(f.b.prec && prec)
454  digits = width - idigits - pch_ind() - prec -1;
455  else
456  digits = width - idigits - pch_ind();
457 
458  while(digits > 0)
459  {
460  pch('0');
461  --digits;
462  }
463  }
464 
465  // Display integer part of number
466  while(idigits > 0)
467  {
468  digit = val;
469 //printf("ival:%.16e, int:%d\n", ival, digit);
470  pch(digit + '0');
471  val -= (double) digit;
472  --idigits;
473  val *= 10.0;
474  }
475  // display fractional part
476  if(f.b.prec && prec > 0 )
477  {
478  pch('.');
479  while(prec > 0 )
480  {
481  digit = val;
482  val -= (double) digit;
483  digit += '0';
484  pch(digit);
485  --prec;
486  val *= 10.0;
487  }
488  }
489  pch(0);
490  return(strlen(save));
491 }
492 
493 
494 
501 MEMSPACE
502 int p_etoa(double val,char *str, int max, int width, int prec, f_t f)
503 {
504  double fscale;
505  int digits;
506  int digit;
507  int exp10;
508  uint8_t exp10_str[7]; // +E123 and EOS
509  int expsize;
510  int i;
511  int sign_ch;
512 
513  pch_init(str,max);
514 
515 /* FIXME
516 Notice rounding - testing will be tricky
517 ERROR: [% 15.1f], [-10252956608208.250000]
518  G[-10252956608208.2]
519  B[-10252956608208.3]
520  error:9.90567929632045986708e-15
521 
522 */
523 //printf("val:%.20e\n", val);
524 //print_flags(f);
525  if(val < 0.0)
526  {
527  val = -val;
528  f.b.neg = 1;
529  }
530  if(f.b.neg)
531  pch('-');
532  else if(f.b.plus)
533  pch('+');
534  else if(f.b.space)
535  pch(' ');
536 
537  // prec only applies to fractional digits
538  if(prec < 0)
539  prec = 0;
540 
541  // NOTE: prec is anchored at the decimal point
542 
543  fscale = 1.0; // rounding value if prec = 0
544  exp10 = 0;
545 
546  if(val) // if zero no rounding needed
547  {
548  fscale = 0.5; // rounding value if prec = 0
549  // do rounding - IF precision specified
550  // number of fractional digits to display
551  if(f.b.prec)
552  {
553  digits = prec;
554  while(digits > 0)
555  {
556  fscale /= 10.0; // adjust rounding value
557  --digits;
558  }
559  }
560 
561  // scale number 1.0 <= x < 10.0
562  while(val < 1.0 )
563  {
564  val *= 10.0;
565  exp10--;
566 
567  }
568  while(val >= 10.0)
569  {
570  ++exp10;
571  val /= 10.0;
572  }
573  val += fscale;
574  while(val >= 10.0)
575  {
576  ++exp10;
577  val /= 10.0;
578  }
579  // round
580  //printf("val;:%.20e, fscale:%.20e\n", val, fscale);
581  //val += fscale; // round to prec
582  }
583 
584  // ====================
585  // Exponent
586  exp10_str[0] = 'e';
587  if ( exp10 < 0 )
588  {
589  sign_ch = '-';
590  exp10 = -exp10;
591  }
592  else
593  {
594  sign_ch = '+';
595  }
596  // result is +NN[N] if we have three digits shorten digits by one
597  expsize = bin2num(exp10_str+1, sizeof(exp10_str)-1-1, 2, 10, (uint8_t *) &exp10, sizeof(int), sign_ch);
598 
599 #if 0
600  if ( exp10 < 0 )
601  {
602  exp10_str[1] = '-';
603  exp10 = -exp10;
604  }
605  else
606  {
607  exp10_str[1] = '+';
608  }
609  if(exp >= 100)
610  ind = 4;
611  else
612  ind = 3;
613 
614  exp10_str[ind] = '0' + (exp % 10);
615  exp10 /= 10;
616  exp10_str[ind] = '0' + (exp % 10);
617  exp10 /= 10;
618  exp10_str[ind] = '0' + (exp % 10);
619 #endif
620 
621  // ====================
622 
623  // [+]N.FFe+00, where ".e+00" = 5 digits, pch_ind holds optional sign offset
624  if(f.b.zero && !f.b.left)
625  {
626  if(f.b.prec && prec)
627  digits = width - pch_ind() - prec - 6;
628  else
629  digits = width - pch_ind() - 5;
630  if(expsize > 3)
631  --digits;
632  while(digits > 0)
633  {
634  pch('0');
635  --digits;
636  }
637  }
638 
639 
640  // Number
641  digit = val;
642 //printf("ival:%.16e, int:%d\n", ival, digit);
643  pch(digit + '0');
644  val -= (double) digit;
645  val *= 10.0;
646 
647  // display fractional part
648  if(f.b.prec && prec > 0 )
649  {
650  pch('.');
651  while(prec > 0 )
652  {
653  digit = val;
654  val -= (double) digit;
655  digit += '0';
656  pch(digit);
657  val *= 10.0;
658  --prec;
659  }
660  }
661 
662  for(i=0;exp10_str[i];++i)
663  pch(exp10_str[i]);
664 
665  pch(0);
666  return(strlen(str));
667 }
668 
669 #endif
670 
671 
672 
673 // =============================================
674 // _puts_pad
675 // Put string count bytes long, padded up to width, left or right aligned
676 // Padding is always done with spaces
677 //
678 // count number of characters to copy from buff
679 // width number of characters to pad up to - if needed
680 // left string is left aligned
681 //_puts(buff, width, count, left);
682 MEMSPACE
683 void _puts_pad(printf_t *fn, char *s, int width, int count, int left)
684 {
685  int size = 0;
686  int pad = 0;
687 
688  // note - if width > count we pad
689  // if width <= count we do not pad
690  if(width > count)
691  {
692  pad = width - count;
693  }
694 
695 //printf("_puts_pad:(%s) width:%d, count:%d, left:%d, pad:%d, len:%d\n", s, width, count, left, pad, len);
696 
697  // left padding ?
698  if(!left)
699  {
700 //printf("_puts_pad:pad:%d\n", pad);
701  while(pad--)
702  {
703  fn->put(fn,' ');
704  ++size;
705  }
706  }
707 //printf("_puts_pad:count:%d\n", count);
708 
709  // string
710  while(*s && count--)
711  {
712  fn->put(fn,*s);
713  ++s;
714  ++size;
715  }
716  // right padding
717  if(left)
718  {
719 //printf("_puts_pad:pad:%d\n", pad);
720 
721  while(pad--)
722  {
723  fn->put(fn,' ');
724  ++size;
725  }
726  }
727 //printf("_puts_pad:size:%d\n", size);
728 } // _puts_pad()
729 
730 
731 
732 
733 
734 
740 MEMSPACE
741 void _printf_fn(printf_t *fn, __memx const char *fmt, va_list va)
742 {
743  int prec, width;
744  int count;
745  int spec;
746  int size;
747  int sign;
748  short nums;
749  int numi;
750  long numl;
751  long long numll;
752  void * numv;
753 #ifdef __SIZEOF_INT128__
754  __uint128_t num128;
755 #endif
756  uint8_t *nump;
757 
758  f_t f;
759 #ifdef FLOATIO
760  double dnum = 0;
761 #endif
762  char chartmp[2];
763  char *ptr;
764  __memx const char *fmtptr;
765 
766  // buff has to be at least as big at the largest converted number
767  // in this case base 2 long long with sign and end of string
768 #ifdef PRINTF_TEST
769  char buff[307 * 2 + 5 + 1]; // double to full size
770 #else
771  char buff[sizeof( long long ) * 8 + 2];
772 #endif
773 
774  while(*fmt)
775  {
776  // emit up to %
777  if(*fmt != '%')
778  {
779  fn->put(fn,*fmt++);
780  continue;
781  }
782 
783  fmtptr = fmt;
784  // process % specifier
785  fmt++;
786 
787  prec = 0; // minimum number of digits displayed
788  width = 0; // padded width
789 
790 
791  // we accept multiple flag combinations and duplicates as does GLIBC printf
792  // ['#']['-'][' '|'+']
793  // [' '|'+']['-']['#']
794  // ...
795 
796  // reset flags
797  f.all = 0;
798  while(*fmt == '#' || *fmt == '+' || *fmt == '-' || *fmt == ' ' || *fmt == '0')
799  {
800  if(*fmt == '#')
801  f.b.alt = 1;
802  else if(*fmt == '+')
803  f.b.plus = 1;
804  else if(!f.b.left && *fmt == '-')
805  f.b.left = 1;
806  else if(!f.b.space && *fmt == ' ')
807  f.b.space = 1;
808  else if(!f.b.zero && *fmt == '0')
809  f.b.zero = 1;
810  // format error
811  ++fmt;
812  }
813 
814  // width specifier
815  // Note: we permit zero as the first digit
816  if(isdigit(*fmt))
817  {
818  // optional width
819  width = 0;
820  while(isdigit(*fmt))
821  width = width*10 + *fmt++ - '0';
822  f.b.width = 1;
823  }
824 
825  // prec always impiles zero fill to prec digigits for ints and longs
826  // is the number of digits after the . for float and double
827  // regardlles of sign
828  if( *fmt == '.' )
829  {
830  fmt++;
831  prec = 0;
832  while(isdigit(*fmt))
833  prec = prec*10 + *fmt++ - '0';
834  f.b.prec = 1;
835  }
836 
842  size = sizeof(int); // int is default
843 
844  if( *fmt == 'I' )
845  {
846  fmt++;
847  size = 0;
848  while(isdigit(*fmt))
849  size = size*10 + *fmt++ - '0';
850  if(size == 0 || size & 7)
851  size = 0;
852  else
853  size >>= 3;
854  }
855  else if(*fmt == 'h')
856  {
857  fmt++;
858  size = sizeof(short);
859  }
860  else if(*fmt == 'l')
861  {
862  fmt++;
863  size = sizeof(long);
864  if(*fmt == 'l')
865  {
866  fmt++;
867  size = sizeof(long long);
868  }
869  }
870 
871  if(size)
872  spec = *fmt;
873  else
874  spec = 0;
875 
876  sign = 0;
877  if(spec == 'd' || spec == 'D')
878  sign = 1;
879 
880 
881  nump = (uint8_t *) &numi;
882 
883  // process integer arguments
884  switch(spec)
885  {
886  case 'p':
887  case 'P':
888  size = sizeof(void *);
889  // Unsigned numbers
890  case 'b':
891  case 'B':
892  case 'o':
893  case 'O':
894  case 'x':
895  case 'X':
896  if(f.b.zero && f.b.left)
897  f.b.zero = 0;
898  if(f.b.zero && f.b.prec)
899  f.b.zero = 0;
900  if(f.b.zero && f.b.width)
901  {
902  if(width > prec)
903  prec = width;
904  }
905  if(f.b.zero && f.b.width && f.b.prec)
906  {
907  if(width > prec)
908  prec = width;
909  }
910  case 'u':
911  case 'U':
912  f.b.space = 0;
913  f.b.plus = 0;
914  f.b.neg = 0;
915  case 'D':
916  case 'd':
917  // make lint shut up
918 //FIXME vararg functions promote short - make this a conditional
919  if(size == sizeof(short))
920  {
921  nums = (short) va_arg(va, int);
922  if(sign && nums < 0)
923  {
924  f.b.neg = 1;
925  nums = -nums;
926  }
927  nump = (uint8_t *) &nums;
928  }
929  else if(size == sizeof(int))
930  {
931  numi = (int) va_arg(va, int);
932  if(sign && numi < 0)
933  {
934  f.b.neg = 1;
935  numi = -numi;
936  }
937  nump = (uint8_t *) &numi;
938  }
939  else if(size == sizeof(long))
940  {
941  numl = (long) va_arg(va, long);
942  if(sign && numl < 0)
943  {
944  f.b.neg = 1;
945  numl = -numl;
946  }
947  nump = (uint8_t *) &numl;
948  }
949  else if(size == sizeof(long long))
950  {
951  numll = (long long) va_arg(va, long long);
952  if(sign && numll < 0)
953  {
954  f.b.neg = 1;
955  numll = -numll;
956  }
957  nump = (uint8_t *) &numll;
958  }
959 #ifdef __SIZEOF_INT128__
960  else if(size == sizeof(__uint128_t))
961  {
962  num128 = (__uint128_t) va_arg(va, __uint128_t);
963  if(sign && numll < 0)
964  {
965  f.b.neg = 1;
966  num128 = -128;
967  }
968  nump = (uint8_t *) &num128;
969  }
970 #endif
971  else if(size == sizeof(void *))
972  {
973  numv = (void *) va_arg(va, void *);
974  nump = (uint8_t *) &numv;
975  }
976  else
977  {
978  spec = 0;
979  }
980  // FIXME default;
981  ++fmt;
982  break;
983 #ifdef FLOATIO
984  case 'f':
985  case 'F':
986  case 'e':
987  case 'E':
988  // K&R defines 'f' type as 6 - and matches GNU printf
989  if(!f.b.prec)
990  {
991  prec = 6;
992  f.b.prec = 1;
993  }
994  dnum = va_arg(va, double);
995  ++fmt;
996  break;
997 #endif
998  case 's':
999  ++fmt;
1000  break;
1001  case 'c':
1002  ++fmt;
1003  break;
1004  default:
1005  break;
1006  }
1007 
1008  switch(spec)
1009  {
1010  case 'u':
1011  case 'U':
1012  f.b.space = 0;
1013  f.b.plus = 0;
1014  // FIXME sign vs FILL
1015  //count = p_itoa(nump, size, buff, sizeof(buff), width, prec, f);
1016  count = p_ntoa(nump, size, buff, sizeof(buff), 10, width, prec, f);
1017  _puts_pad(fn,buff, width, count, f.b.left);
1018  break;
1019  // FIXME sign vs FILL
1020  case 'd':
1021  case 'D':
1022  count = p_ntoa(nump, size, buff, sizeof(buff), 10, width, prec, f);
1023  _puts_pad(fn,buff, width, count, f.b.left);
1024  break;
1025  case 'b':
1026  case 'B':
1027  count = p_ntoa(nump, size, buff, sizeof(buff), 2, width, prec,f);
1028  _puts_pad(fn,buff, width, count, f.b.left);
1029  break;
1030  case 'o':
1031  case 'O':
1032  count = p_ntoa(nump, size, buff, sizeof(buff), 8, width, prec,f);
1033  _puts_pad(fn,buff, width, count, f.b.left);
1034  break;
1035  case 'p':
1036  case 'P':
1037  // size = sizeof(void *);
1038  case 'x':
1039  case 'X':
1040  count = p_ntoa(nump, size, buff, sizeof(buff), 16, width, prec,f);
1041  if(spec == 'X' || spec == 'P')
1042  strupper(buff);
1043  _puts_pad(fn,buff, width, count, f.b.left);
1044  break;
1045 #ifdef FLOATIO
1046  case 'f':
1047  case 'F':
1048  count = p_ftoa(dnum, buff, sizeof(buff), width, prec, f);
1049  _puts_pad(fn,buff, width, count, f.b.left);
1050  break;
1051 
1052  case 'e':
1053  case 'E':
1054  count = p_etoa(dnum, buff, sizeof(buff), width, prec, f);
1055  if(spec == 'E')
1056  strupper(buff);
1057  _puts_pad(fn,buff, width, count, f.b.left);
1058  break;
1059 #endif
1060  case 's':
1061  case 'c':
1062  ptr = NULL; // stops bogus error that ptr may be uninitalized
1063  if(spec == 's')
1064  {
1065  ptr = va_arg(va, char *);
1066  if(!ptr)
1067  ptr = "(null)";
1068  }
1069  else // 'c'
1070  {
1071  chartmp[0] = (char) va_arg(va, int);
1072  chartmp[1] = 0;
1073  ptr = chartmp;
1074  }
1075  count = strlen(ptr);
1076  if(prec)
1077  count = prec;
1078  if(count > width && width != 0)
1079  count = width;
1080 //printf("width:%d,count:%d,left:%d\n", width, count, f.b.left);
1081  _puts_pad(fn,ptr, width, count, f.b.left);
1082  break;
1083  default:
1084  while(fmtptr <= fmt && *fmtptr)
1085  fn->put(fn, *fmtptr++);
1086  break;
1087  }
1088 //printf("fmt:(%s)\n", fmt);
1089  }
1090 //printf("fmt exit:(%s)\n", fmt);
1091 
1092 }
1093 
1094 
1095 // =============================================
1102 MEMSPACE
1103 void _putc_buffer_fn(struct _printf_t *p, char ch)
1104 {
1105  char *str;
1106  if (p->len )
1107  {
1108  if(ch)
1109  {
1110  p->len--;
1111  p->sent++;
1112  str = (char *) p->buffer;
1113  *str++ = ch;
1114  p->buffer = (void *) str;
1115  }
1116  }
1117  *((char *)p->buffer) = 0;
1118 }
1119 
1120 #ifdef PRINTF_TEST
1121 #ifdef DEFINE_PRINTF
1122 #error DEFINE_PRINTF must not be defined when testing
1123 #endif
1124 #endif
1125 
1126 #ifndef PRINTF_TEST
1127 // =============================================
1134 MEMSPACE
1135 int vsnprintf(char* str, size_t size, const char *format, va_list va)
1136 {
1137 
1138  int len;
1139  char *save = str;
1140  printf_t fn;
1141 
1142  *str = 0;
1143 
1144  fn.put = _putc_buffer_fn;
1145  fn.len = size;
1146  fn.sent = 0;
1147  fn.buffer = (void *) str;
1148 
1149  _printf_fn(&fn, format, va);
1150 
1151  // FIXME check size should == fn.size on exit
1152  len = strlen(save);
1153  return( len );
1154 }
1155 
1156 // =============================================
1163 MEMSPACE
1164 int snprintf(char* str, size_t size, const char *format, ...)
1165 {
1166  int len;
1167  va_list va;
1168 
1169  va_start(va, format);
1170  len = vsnprintf(str, size, format, va);
1171  va_end(va);
1172 
1173  return len;
1174 }
1175 
1176 #ifdef AVR
1177 MEMSPACE
1184 int vsnprintf_P(char* str, size_t size, __memx const char *format, va_list va)
1185 {
1186 
1187  int len;
1188  char *save = str;
1189  printf_t fn;
1190 
1191  *str = 0;
1192 
1193  fn.put = _putc_buffer_fn;
1194  fn.len = size;
1195  fn.sent = 0;
1196  fn.buffer = (void *) str;
1197 
1198  _printf_fn(&fn, format, va);
1199 
1200  // FIXME check size should == fn.size on exit
1201  len = strlen(save);
1202  return( len );
1203 }
1204 
1211 MEMSPACE
1212 int snprintf_P(char* str, size_t size, __memx const char *format, ...)
1213 {
1214  int len;
1215  va_list va;
1216 
1217  va_start(va, format);
1218  len = vsnprintf_P(str, size, format, va);
1219  va_end(va);
1220 
1221  return len;
1222 }
1223 
1229 MEMSPACE
1230 int sprintf_P(char* str, __memx const char *format, ...)
1231 {
1232  int len;
1233  va_list va;
1234 
1235  va_start(va, format);
1236  // FIXME max string size limit !!!!
1237  len = vsnprintf_P(str, 1024, format, va);
1238  va_end(va);
1239 
1240  return len;
1241 }
1242 #endif
1243 // =============================================
1245 // =============================================
1246 
1247 #ifdef DEFINE_PRINTF
1248 // =============================================
1254 MEMSPACE
1255 static void _putc_fn(struct _printf_t *p, char ch)
1256 {
1257  p->sent++;
1258  putchar(ch);
1259 }
1260 
1268 MEMSPACE
1269 int
1270 printf(const char *format, ...)
1271 {
1272  printf_t fn;
1273  va_list va;
1274 
1275  fn.put = _putc_fn;
1276  fn.sent = 0;
1277 
1278  va_start(va, format);
1279  _printf_fn(&fn, format, va);
1280  va_end(va);
1281 
1282  return ((int)fn.sent);
1283 }
1284 #ifdef AVR
1285 MEMSPACE
1293 int
1294 printf_P(__memx const char *format, ...)
1295 {
1296  printf_t fn;
1297  va_list va;
1298 
1299  fn.put = _putc_fn;
1300  fn.sent = 0;
1301 
1302  va_start(va, format);
1303  _printf_fn(&fn, format, va);
1304  va_end(va);
1305 
1306  return ((int)fn.sent);
1307 }
1308 #endif
1309 #endif
1310 #endif
unsigned short left
Definition: mathio.h:95
MEMSPACE int bin2num(uint8_t *str, int strmax, int nummin, int base, uint8_t *nump, int numsize, int sign_ch)
Convert an unsigned number (numsize bytes in size) to ASCII in specified base Notes: No limit except ...
Definition: printf.c:139
Data structure for character buffer with limits.
Definition: printf.c:208
#define __memx
Definition: mathio.h:38
unsigned short prec
Definition: mathio.h:93
Master include file for project Includes all project includes and defines here.
MEMSPACE int WEAK_ATR isdigit(int c)
test if a character is a digit
Definition: printf.c:70
MEMSPACE size_t WEAK_ATR strlen(const char *str)
String Length.
Definition: printf.c:53
MEMSPACE int snprintf(char *str, size_t size, const char *format,...)
snprintf function
Definition: printf.c:1164
MEMSPACE int p_ntoa(uint8_t *nump, int numsize, char *str, int strmax, int radix, int width, int prec, f_t f)
Convert number an base 2 .. 16 to ASCII with optional sign Notes: 1) Numbers can be any number of dig...
Definition: printf.c:314
int ind
base of string to write to
Definition: printf.c:210
struct f_t::@2 b
MEMSPACE void _puts_pad(printf_t *fn, char *s, int width, int count, int left)
Definition: printf.c:683
MEMSPACE void print_flags(f_t f)
print flags set in t_t structure
Definition: printf.c:270
unsigned short neg
Definition: mathio.h:98
MEMSPACE void WEAK_ATR reverse(char *str)
Reverse a string in place Example: abcdef -> fedcba.
Definition: printf.c:88
unsigned short plus
Definition: mathio.h:94
int putchar(int c)
put a character to stdout See fdevopen() sets stream->put get for TTY devices
Definition: posix.c:351
MEMSPACE void _putc_buffer_fn(struct _printf_t *p, char ch)
_putc_buffer_fn - character output to a string buffer Used by snprintf and vsnprintf You can make _pr...
Definition: printf.c:1103
MEMSPACE int vsnprintf(char *str, size_t size, const char *format, va_list va)
vsnprintf function
Definition: printf.c:1135
#define NULL
Definition: cpu.h:55
unsigned short zero
Definition: mathio.h:97
MEMSPACE void WEAK_ATR strupper(char *str)
UPPERCASE a string.
Definition: printf.c:109
Math IO functions, and verious conversion code with floating point support.
int ind
Definition: ili9341.c:373
unsigned short space
Definition: mathio.h:96
void * buffer
Definition: mathio.h:84
int len
Definition: mathio.h:85
unsigned short width
Definition: mathio.h:92
MEMSPACE void _printf_fn(printf_t *fn, __memx const char *fmt, va_list va)
vsnprintf function
Definition: printf.c:741
#define MEMSPACE
Definition: cpu.h:25
MEMSPACE int pch_max_ind()
Return maximum valid index for character buffer.
Definition: printf.c:258
unsigned short all
Definition: mathio.h:101
MEMSPACE int printf(const char *format,...)
#define WEAK_ATR
Definition: stringsup.h:33
MEMSPACE int p_etoa(double val, char *str, int max, int width, int prec, f_t f)
unsigned short alt
Definition: mathio.h:99
int sent
Definition: mathio.h:86
MEMSPACE int pch_ind()
Return current index of character buffer with limits.
Definition: printf.c:250
MEMSPACE void pch_init(char *str, int max)
Initialize character buffer with limits.
Definition: printf.c:222
MEMSPACE int pch(char ch)
Put character in buffer with limits.
Definition: printf.c:237
char * str
Definition: printf.c:209
format specifier flags
Definition: mathio.h:90
int max
current string index
Definition: printf.c:211
unsigned char uint8_t
Definition: send.c:17
MEMSPACE int p_ftoa(double val, char *str, int max, int width, int prec, f_t f)
void(* put)(struct _printf_t *, char)
Definition: mathio.h:83
undefine any potential macro version of these functions
Definition: mathio.h:81
p_ch_t _pch
Define data structure for character buffer with limits.
Definition: printf.c:215