Usermode/libc-libposix - Features for SpiderWeb/SpiderScript
[tpg/acess2.git] / Usermode / Libraries / libc.so_src / stdio.c
1 /*\r
2  * AcessOS Basic C Library\r
3  * stdio.c\r
4  */\r
5 #include "config.h"\r
6 #include <acess/sys.h>\r
7 #include <stdlib.h>\r
8 #include <stdio.h>\r
9 #include <string.h>\r
10 #include "lib.h"\r
11 #include "stdio_int.h"\r
12 \r
13 #define WRITE_STR(_fd, _str)    write(_fd, _str, sizeof(_str))\r
14 \r
15 #define DEBUG_BUILD     0\r
16 \r
17 // === CONSTANTS ===\r
18 #define _stdin  0\r
19 #define _stdout 1\r
20 \r
21 // === PROTOTYPES ===\r
22 EXPORT void     itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned);\r
23 struct sFILE    *get_file_struct();\r
24 \r
25 // === GLOBALS ===\r
26 struct sFILE    _iob[STDIO_MAX_STREAMS];        // IO Buffer\r
27 struct sFILE    *stdin; // Standard Input\r
28 struct sFILE    *stdout;        // Standard Output\r
29 struct sFILE    *stderr;        // Standard Error\r
30 ///\note Initialised in SoMain\r
31 \r
32 // === CODE ===\r
33 int _fopen_modetoflags(const char *mode)\r
34 {\r
35         int flags = 0;\r
36         \r
37         // Get main mode\r
38         switch(*mode)\r
39         {\r
40         case 'r':       flags = FILE_FLAG_MODE_READ;    break;\r
41         case 'w':       flags = FILE_FLAG_MODE_WRITE;   break;\r
42         case 'a':       flags = FILE_FLAG_MODE_APPEND;  break;\r
43         case 'x':       flags = FILE_FLAG_MODE_EXEC;    break;  // Acess addon\r
44         default:\r
45                 return -1;\r
46         }\r
47         mode ++;\r
48 \r
49         // Get Modifiers\r
50         for( ; *mode; mode ++ )\r
51         {\r
52                 switch(*mode)\r
53                 {\r
54                 case 'b':       flags |= FILE_FLAG_M_BINARY;    break;\r
55                 case '+':       flags |= FILE_FLAG_M_EXT;       break;\r
56                 default:\r
57                         return -1;\r
58                 }\r
59         }\r
60         \r
61         return flags;\r
62 }\r
63 \r
64 /**\r
65  * \fn FILE *freopen(char *file, char *mode, FILE *fp)\r
66  */\r
67 EXPORT FILE *freopen(const char *file, const char *mode, FILE *fp)\r
68 {\r
69          int    openFlags = 0;\r
70         \r
71         // Sanity Check Arguments\r
72         if(!fp || !file || !mode)       return NULL;\r
73         \r
74         if(fp->FD != -1) {\r
75                 fflush(fp);\r
76         }\r
77 \r
78         // Get stdio flags\r
79         fp->Flags = _fopen_modetoflags(mode);\r
80         if(fp->Flags == -1)\r
81                 return NULL;\r
82         \r
83         // Get Open Flags\r
84         switch(fp->Flags & FILE_FLAG_MODE_MASK)\r
85         {\r
86         // Read\r
87         case FILE_FLAG_MODE_READ:\r
88                 openFlags = OPENFLAG_READ;\r
89                 if(fp->Flags & FILE_FLAG_M_EXT)\r
90                         openFlags |= OPENFLAG_WRITE;\r
91                 break;\r
92         // Write\r
93         case FILE_FLAG_MODE_WRITE:\r
94                 openFlags = OPENFLAG_WRITE;\r
95                 if(fp->Flags & FILE_FLAG_M_EXT)\r
96                         openFlags |= OPENFLAG_READ;\r
97                 break;\r
98         // Execute\r
99         case FILE_FLAG_MODE_APPEND:\r
100                 openFlags = OPENFLAG_APPEND;\r
101                 if(fp->Flags & FILE_FLAG_M_EXT)\r
102                         openFlags |= OPENFLAG_READ;\r
103                 break;\r
104         // Execute\r
105         case FILE_FLAG_MODE_EXEC:\r
106                 openFlags = OPENFLAG_EXEC;\r
107                 break;\r
108         }\r
109 \r
110         //Open File\r
111         if(fp->FD != -1)\r
112                 fp->FD = _SysReopen(fp->FD, file, openFlags);\r
113         else\r
114                 fp->FD = _SysOpen(file, openFlags);\r
115         if(fp->FD == -1) {\r
116                 fp->Flags = 0;\r
117                 return NULL;\r
118         }\r
119         \r
120         if( (fp->Flags & FILE_FLAG_MODE_MASK) == FILE_FLAG_MODE_APPEND ) {\r
121                 _SysSeek(fp->FD, 0, SEEK_END);  //SEEK_END\r
122         }\r
123         \r
124         return fp;\r
125 }\r
126 /**\r
127  \fn FILE *fopen(const char *file, const char *mode)\r
128  \brief Opens a file and returns the pointer\r
129  \param file    String - Filename to open\r
130  \param mode    Mode to open in\r
131 */\r
132 EXPORT FILE *fopen(const char *file, const char *mode)\r
133 {\r
134         FILE    *retFile;\r
135         \r
136         // Sanity Check Arguments\r
137         if(!file || !mode)      return NULL;\r
138         \r
139         // Create Return Structure\r
140         retFile = get_file_struct();\r
141         \r
142         return freopen(file, mode, retFile);\r
143 }\r
144 \r
145 EXPORT FILE *fmemopen(void *buffer, size_t length, const char *mode)\r
146 {\r
147         FILE    *ret;\r
148         \r
149         if( !buffer || !mode )  return NULL;\r
150         \r
151         ret = get_file_struct();\r
152         \r
153         ret->FD = -2;\r
154         ret->Flags = _fopen_modetoflags(mode);\r
155         if(ret->Flags == -1) {\r
156                 ret->Flags = 0;\r
157                 return NULL;\r
158         }\r
159         \r
160         ret->Buffer = buffer;\r
161         ret->BufferStart = 0;\r
162         ret->BufferSize = length;\r
163         \r
164         return ret;\r
165 }\r
166 \r
167 EXPORT int fclose(FILE *fp)\r
168 {\r
169         fflush(fp);\r
170         if( fp->FD != -1 ) {\r
171                 _SysClose(fp->FD);\r
172         }\r
173         fp->Flags = 0;\r
174         fp->FD = -1;\r
175         return 0;\r
176 }\r
177 \r
178 EXPORT void fflush(FILE *fp)\r
179 {\r
180         if( !fp || fp->FD == -1 )\r
181                 return ;\r
182         \r
183         if( !(fp->Flags & FILE_FLAG_DIRTY) )\r
184                 return ;\r
185         \r
186         // Nothing to do for memory files\r
187         if( fp->FD == -2 )\r
188                 return ;\r
189 }\r
190 \r
191 EXPORT void clearerr(FILE *fp)\r
192 {\r
193         if( !fp || fp->FD == -1 )\r
194                 return ;\r
195         \r
196         // TODO: Impliment clearerr()\r
197 }\r
198 \r
199 EXPORT int feof(FILE *fp)\r
200 {\r
201         if( !fp || fp->FD == -1 )\r
202                 return 0;\r
203         return !!(fp->Flags & FILE_FLAG_EOF);\r
204 }\r
205 \r
206 EXPORT int ferror(FILE *fp)\r
207 {\r
208         if( !fp || fp->FD == -1 )\r
209                 return 0;\r
210         return 0;\r
211 }\r
212 EXPORT int fileno(FILE *stream)\r
213 {\r
214         return stream->FD;\r
215 }\r
216 \r
217 EXPORT off_t ftell(FILE *fp)\r
218 {\r
219         if(!fp || fp->FD == -1) return -1;\r
220 \r
221         if( fp->FD == -2 )\r
222                 return fp->Pos; \r
223         else\r
224                 return _SysTell(fp->FD);\r
225 }\r
226 \r
227 EXPORT int fseek(FILE *fp, long int amt, int whence)\r
228 {\r
229         if(!fp || fp->FD == -1) return -1;\r
230 \r
231         if( fp->FD == -2 ) {\r
232                 switch(whence)\r
233                 {\r
234                 case SEEK_CUR:\r
235                         fp->Pos += amt;\r
236                         break;\r
237                 case SEEK_SET:\r
238                         fp->Pos = amt;\r
239                         break;\r
240                 case SEEK_END:\r
241                         if( fp->BufferSize < (size_t)amt )\r
242                                 fp->Pos = 0;\r
243                         else\r
244                                 fp->Pos = fp->BufferSize - amt;\r
245                         break;\r
246                 }\r
247                 if(fp->Pos > (off_t)fp->BufferSize) {\r
248                         fp->Pos = fp->BufferSize;\r
249                         fp->Flags |= FILE_FLAG_EOF;\r
250                 }\r
251                 return 0;\r
252         }\r
253         else\r
254                 return _SysSeek(fp->FD, amt, whence);\r
255 }\r
256 \r
257 \r
258 /**\r
259  * \fn EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
260  * \brief Print to a file from a variable argument list\r
261  */\r
262 EXPORT int vfprintf(FILE *fp, const char *format, va_list args)\r
263 {\r
264         va_list tmpList;\r
265          int    size;\r
266 \r
267         if(!fp || !format)      return -1;\r
268 \r
269         va_copy(tmpList, args);\r
270         \r
271         size = vsnprintf(NULL, 0, (char*)format, tmpList);\r
272         char    buf[size+1];\r
273         vsnprintf(buf, size+1, (char*)format, args);\r
274         \r
275         // Write to stream\r
276         fwrite(buf, size, 1, fp);\r
277         \r
278         // Return written byte count\r
279         return size;\r
280 }\r
281 \r
282 /**\r
283  * \fn int fprintf(FILE *fp, const char *format, ...)\r
284  * \brief Print a formatted string to a stream\r
285  */\r
286 EXPORT int fprintf(FILE *fp, const char *format, ...)\r
287 {\r
288         va_list args;\r
289          int    ret;\r
290         \r
291         // Get Size\r
292         va_start(args, format);\r
293         ret = vfprintf(fp, (char*)format, args);\r
294         va_end(args);\r
295         \r
296         return ret;\r
297 }\r
298 \r
299 /**\r
300  * \fn EXPORT size_t fwrite(void *ptr, size_t size, size_t num, FILE *fp)\r
301  * \brief Write to a stream\r
302  */\r
303 EXPORT size_t fwrite(const void *ptr, size_t size, size_t num, FILE *fp)\r
304 {\r
305         size_t  ret;\r
306         \r
307         if(!fp || fp->FD == -1)\r
308                 return -1;\r
309 \r
310         if( fp->FD == -2 ) {\r
311                 size_t  avail = (fp->BufferSize - fp->Pos) / size;\r
312                 if( avail == 0 )\r
313                         fp->Flags |= FILE_FLAG_EOF;\r
314                 if( num > avail )       num = avail;\r
315                 size_t  bytes = num * size;\r
316                 memcpy((char*)fp->Buffer + fp->Pos, ptr, bytes);\r
317                 fp->Pos += bytes;\r
318                 ret = num;\r
319         }\r
320         else {  \r
321                 ret = _SysWrite(fp->FD, ptr, size*num);\r
322                 ret /= size;\r
323         }\r
324         \r
325         return ret;\r
326 }\r
327 \r
328 /**\r
329  * \fn EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
330  * \brief Read from a stream\r
331  */\r
332 EXPORT size_t fread(void *ptr, size_t size, size_t num, FILE *fp)\r
333 {\r
334         size_t  ret;\r
335         \r
336         if(!fp || fp->FD == -1)\r
337                 return -1;\r
338 \r
339         if( fp->FD == -2 ) {\r
340                 size_t  avail = (fp->BufferSize - fp->Pos) / size;\r
341                 if( avail == 0 )\r
342                         fp->Flags |= FILE_FLAG_EOF;\r
343                 if( num > avail )       num = avail;\r
344                 size_t  bytes = num * size;\r
345                 memcpy(ptr, (char*)fp->Buffer + fp->Pos, bytes);\r
346                 fp->Pos += bytes;\r
347                 ret = num;\r
348         }\r
349         else {\r
350                 ret = _SysRead(fp->FD, ptr, size*num);\r
351                 ret /= size;\r
352         }\r
353                 \r
354         return ret;\r
355 }\r
356 \r
357 /**\r
358  * \brief Write a string to a stream (without trailing \n)\r
359  */\r
360 EXPORT int fputs(const char *s, FILE *fp)\r
361 {\r
362         int len = strlen(s);\r
363         return fwrite(s, 1, len, fp);\r
364 }\r
365 \r
366 /**\r
367  * \brief Read a line (and possible trailing \n into a buffer)\r
368  */\r
369 EXPORT char *fgets(char *s, int size, FILE *fp)\r
370 {\r
371         int ofs = 0;\r
372         char    ch = '\0';\r
373         while( ofs < size && ch != '\n' )\r
374         {\r
375                 if( fread(&ch, 1, 1, fp) != 1 )\r
376                         break;\r
377                 s[ofs ++] = ch;\r
378         }\r
379         if( ofs < size )\r
380                 s[ofs] = '\0';\r
381         return s;\r
382 }\r
383 \r
384 /**\r
385  * \fn EXPORT int fputc(int c, FILE *fp)\r
386  * \brief Write a single character to the stream\r
387  */\r
388 EXPORT int fputc(int c, FILE *fp)\r
389 {\r
390         return fwrite(&c, 1, 1, fp);\r
391 }\r
392 \r
393 EXPORT int putchar(int c)\r
394 {\r
395         c &= 0xFF;\r
396         return _SysWrite(_stdout, &c, 1);\r
397 }\r
398 \r
399 /**\r
400  * \fn EXPORT int fgetc(FILE *fp)\r
401  * \brief Read a character from the stream\r
402  */\r
403 EXPORT int fgetc(FILE *fp)\r
404 {\r
405         char    ret = 0;\r
406         if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
407                 return -1;\r
408         return ret;\r
409 }\r
410 \r
411 EXPORT int getchar(void)\r
412 {\r
413         char    ret = 0;\r
414         if(_SysRead(_stdin, &ret, 1) != 1)      return -1;\r
415         return ret;\r
416 }\r
417 \r
418 // --- INTERNAL ---\r
419 /**\r
420  * \fn FILE *get_file_struct()\r
421  * \brief Returns a file descriptor structure\r
422  */\r
423 FILE *get_file_struct()\r
424 {\r
425          int    i;\r
426         for(i=0;i<STDIO_MAX_STREAMS;i++)\r
427         {\r
428                 if(_iob[i].Flags & FILE_FLAG_ALLOC)\r
429                         continue ;\r
430                 _iob[i].Flags |= FILE_FLAG_ALLOC;\r
431                 _iob[i].FD = -1;\r
432                 _iob[i].Pos = 0;\r
433                 return &_iob[i];\r
434         }\r
435         return NULL;\r
436 }\r
437 \r
438 EXPORT int puts(const char *str)\r
439 {\r
440          int    len;\r
441         \r
442         if(!str)        return 0;\r
443         len = strlen(str);\r
444         \r
445         len = _SysWrite(_stdout, str, len);\r
446         _SysWrite(_stdout, "\n", 1);\r
447         return len;\r
448 }\r
449 \r
450 EXPORT int vsprintf(char * __s, const char *__format, va_list __args)\r
451 {\r
452         return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
453 }\r
454 \r
455 //sprintfv\r
456 /**\r
457  * \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
458  * \brief Prints a formatted string to a buffer\r
459  * \param buf   Pointer - Destination Buffer\r
460  * \param format        String - Format String\r
461  * \param args  VarArgs List - Arguments\r
462  */\r
463 EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)\r
464 {\r
465         char    tmp[65];\r
466          int    c, minSize, precision, len;\r
467         size_t  pos = 0;\r
468         char    *p;\r
469         char    pad;\r
470         uint64_t        arg;\r
471          int    bLongLong, bPadLeft;\r
472 \r
473         void _addchar(char ch)\r
474         {\r
475                 if(buf && pos < __maxlen)       buf[pos] = ch;\r
476                 pos ++;\r
477         }\r
478 \r
479         tmp[32] = '\0';\r
480         \r
481         while((c = *format++) != 0)\r
482         {\r
483                 // Non-control character\r
484                 if (c != '%') {\r
485                         _addchar(c);\r
486                         continue;\r
487                 }\r
488                 \r
489                 // Control Character\r
490                 c = *format++;\r
491                 if(c == '%') {  // Literal %\r
492                         _addchar('%');\r
493                         continue;\r
494                 }\r
495                 \r
496                 bPadLeft = 0;\r
497                 bLongLong = 0;\r
498                 minSize = 0;\r
499                 precision = -1;\r
500                 pad = ' ';\r
501                 \r
502                 // Padding Character\r
503                 if(c == '0') {\r
504                         pad = '0';\r
505                         c = *format++;\r
506                 }\r
507                 // Padding length\r
508                 if( c == '*' ) {\r
509                         // Variable length\r
510                         minSize = va_arg(args, size_t);\r
511                         c = *format++;\r
512                 }\r
513                 else {\r
514                         if('1' <= c && c <= '9')\r
515                         {\r
516                                 minSize = 0;\r
517                                 while('0' <= c && c <= '9')\r
518                                 {\r
519                                         minSize *= 10;\r
520                                         minSize += c - '0';\r
521                                         c = *format++;\r
522                                 }\r
523                         }\r
524                 }\r
525 \r
526                 // Precision\r
527                 if(c == '.') {\r
528                         c = *format++;\r
529                         if(c == '*') {\r
530                                 precision = va_arg(args, size_t);\r
531                                 c = *format++;\r
532                         }\r
533                         else if('1' <= c && c <= '9')\r
534                         {\r
535                                 precision = 0;\r
536                                 while('0' <= c && c <= '9')\r
537                                 {\r
538                                         precision *= 10;\r
539                                         precision += c - '0';\r
540                                         c = *format++;\r
541                                 }\r
542                         }\r
543                 }\r
544         \r
545                 // Check for long long\r
546                 bLongLong = 0;\r
547                 if(c == 'l')\r
548                 {\r
549                         c = *format++;\r
550                         if(c == 'l') {\r
551                                 bLongLong = 1;\r
552                         }\r
553                 }\r
554                 \r
555                 // Just help things along later\r
556                 p = tmp;\r
557                 \r
558                 // Get Type\r
559                 switch( c )\r
560                 {\r
561                 // Signed Integer\r
562                 case 'd':       case 'i':\r
563                         // Get Argument\r
564                         if(bLongLong)   arg = va_arg(args, int64_t);\r
565                         else                    arg = va_arg(args, int32_t);\r
566                         itoa(tmp, arg, 10, minSize, pad, 1);\r
567                         precision = -1;\r
568                         goto sprintf_puts;\r
569                 \r
570                 // Unsigned Integer\r
571                 case 'u':\r
572                         // Get Argument\r
573                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
574                         else                    arg = va_arg(args, uint32_t);\r
575                         itoa(tmp, arg, 10, minSize, pad, 0);\r
576                         precision = -1;\r
577                         goto sprintf_puts;\r
578                 \r
579                 // Pointer\r
580                 case 'p':\r
581                         _addchar('*');\r
582                         _addchar('0');\r
583                         _addchar('x');\r
584                         arg = va_arg(args, intptr_t);\r
585                         itoa(tmp, arg, 16, minSize, pad, 0);\r
586                         precision = -1;\r
587                         goto sprintf_puts;\r
588                 // Unsigned Hexadecimal\r
589                 case 'x':\r
590                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
591                         else                    arg = va_arg(args, uint32_t);\r
592                         itoa(tmp, arg, 16, minSize, pad, 0);\r
593                         precision = -1;\r
594                         goto sprintf_puts;\r
595                 \r
596                 // Unsigned Octal\r
597                 case 'o':\r
598                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
599                         else                    arg = va_arg(args, uint32_t);\r
600                         itoa(tmp, arg, 8, minSize, pad, 0);\r
601                         precision = -1;\r
602                         goto sprintf_puts;\r
603                 \r
604                 // Unsigned binary\r
605                 case 'b':\r
606                         if(bLongLong)   arg = va_arg(args, uint64_t);\r
607                         else                    arg = va_arg(args, uint32_t);\r
608                         itoa(tmp, arg, 2, minSize, pad, 0);\r
609                         precision = -1;\r
610                         goto sprintf_puts;\r
611 \r
612                 // String\r
613                 case 's':\r
614                         p = va_arg(args, char*);\r
615                 sprintf_puts:\r
616                         if(!p)  p = "(null)";\r
617                         //_SysDebug("vsnprintf: p = '%s'", p);\r
618                         if(precision >= 0)\r
619                                 len = strnlen(p, precision);\r
620                         else\r
621                                 len = strlen(p);\r
622                         if(bPadLeft)    while(minSize > len++)  _addchar(pad);\r
623                         while( *p ) {\r
624                                 if(precision >= 0 && precision -- == 0)\r
625                                         break;\r
626                                 _addchar(*p++);\r
627                         }\r
628                         if(!bPadLeft)   while(minSize > len++)  _addchar(pad);\r
629                         break;\r
630 \r
631                 // Unknown, just treat it as a character\r
632                 default:\r
633                         arg = va_arg(args, uint32_t);\r
634                         _addchar(arg);\r
635                         break;\r
636                 }\r
637         }\r
638         _addchar('\0');\r
639         pos --;\r
640         \r
641         //_SysDebug("vsnprintf: buf = '%s'", buf);\r
642         \r
643         return pos;\r
644 }\r
645 \r
646 const char cUCDIGITS[] = "0123456789ABCDEF";\r
647 /**\r
648  * \fn static void itoa(char *buf, uint64_t num, int base, int minLength, char pad, int bSigned)\r
649  * \brief Convert an integer into a character string\r
650  * \param buf   Destination Buffer\r
651  * \param num   Number to convert\r
652  * \param base  Base-n number output\r
653  * \param minLength     Minimum length of output\r
654  * \param pad   Padding used to ensure minLength\r
655  * \param bSigned       Signed number output?\r
656  */\r
657 EXPORT void itoa(char *buf, uint64_t num, size_t base, int minLength, char pad, int bSigned)\r
658 {\r
659         char    tmpBuf[64];\r
660          int    pos=0, i;\r
661 \r
662         if(!buf)        return;\r
663         if(base > 16 || base < 2) {\r
664                 buf[0] = 0;\r
665                 return;\r
666         }\r
667         \r
668         if(bSigned && (int64_t)num < 0)\r
669         {\r
670                 num = -num;\r
671                 bSigned = 1;\r
672         } else\r
673                 bSigned = 0;\r
674         \r
675         // Encode into reversed string\r
676         while(num > base-1) {\r
677                 tmpBuf[pos++] = cUCDIGITS[ num % base ];\r
678                 num = (uint64_t) num / (uint64_t)base;          // Shift {number} right 1 digit\r
679         }\r
680 \r
681         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of {number}\r
682         if(bSigned)     tmpBuf[pos++] = '-';    // Append sign symbol if needed\r
683         \r
684         i = 0;\r
685         minLength -= pos;\r
686         while(minLength-- > 0)  buf[i++] = pad;\r
687         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters\r
688         buf[i] = 0;\r
689 }\r
690 \r
691 /**\r
692  * \fn EXPORT int printf(const char *format, ...)\r
693  * \brief Print a string to stdout\r
694  */\r
695 EXPORT int printf(const char *format, ...)\r
696 {\r
697          int    size;\r
698         va_list args;\r
699         \r
700         // Get final size\r
701         va_start(args, format);\r
702         size = vsnprintf(NULL, 0, (char*)format, args);\r
703         va_end(args);\r
704         char buf[size+1];\r
705         // Fill Buffer\r
706         va_start(args, format);\r
707         vsnprintf(buf, size+1, (char*)format, args);\r
708         va_end(args);\r
709         \r
710         // Send to stdout\r
711         _SysWrite(_stdout, buf, size+1);\r
712         \r
713         // Free buffer\r
714         free(buf);\r
715         // Return\r
716         return size;\r
717 }\r
718 \r
719 /**\r
720  * \fn EXPORT int sprintf(const char *buf, char *format, ...)\r
721  * \brief Print a formatted string to a buffer\r
722  */\r
723 EXPORT int sprintf(char *buf, const char *format, ...)\r
724 {\r
725          int    ret;\r
726         va_list args;\r
727         va_start(args, format);\r
728         ret = vsprintf((char*)buf, (char*)format, args);\r
729         va_end(args);\r
730         return ret;\r
731 }\r
732 \r
733 /**\r
734  * \fn EXPORT int snprintf(const char *buf, size_t maxlen, char *format, ...)\r
735  * \brief Print a formatted string to a buffer\r
736  */\r
737 EXPORT int snprintf(char *buf, size_t maxlen, const char *format, ...)\r
738 {\r
739          int    ret;\r
740         va_list args;\r
741         va_start(args, format);\r
742         ret = vsnprintf((char*)buf, maxlen, (char*)format, args);\r
743         va_end(args);\r
744         return ret;\r
745 }\r

UCC git Repository :: git.ucc.asn.au