2 Copyright (C) 2008 Mathias Gottschlag
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in the
6 Software without restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 FILE *fopen(const char *filename
, const char *mode
)
46 if (strchr(mode
, 'r')) openmode
= O_RDONLY
;
47 else if (strchr(mode
, 'w')) openmode
= O_WRONLY
| O_CREAT
;
48 else if (strchr(mode
, 'a')) openmode
= O_WRONLY
| O_CREAT
;
49 if (strchr(mode
, '+')) openmode
= (openmode
& ~O_ACCMODE
) | O_RDWR
;
50 int fd
= open(filename
, openmode
);
51 if (fd
== -1) return 0;
52 // Return file structure
53 FILE *file
= malloc(sizeof(FILE));
54 memset(file
, 0, sizeof(FILE));
56 if (strchr(mode
, 'a')) file
->append
= 1;
59 int fclose(FILE *file
)
61 if (!file
) return EOF
;
66 FILE *freopen(const char *filename
, const char *mode
, FILE *file
)
68 if (fclose(file
) == EOF
) return 0;
69 return fopen(filename
, mode
);
73 return (file
->error
& ERROR_EOF
) != 0;
75 int ferror(FILE *file
)
77 return (file
->error
& ERROR_ERROR
) != 0;
79 int fseek(FILE *file
, long int offset
, int origin
)
81 if (!file
) return EOF
;
83 if (lseek(file
->fd
, offset
, origin
) == (off_t
)-1) return EOF
;
86 long int ftell(FILE *file
)
88 if (!file
) return EOF
;
89 long int pos
= lseek(file
->fd
, 0, SEEK_CUR
);
92 void rewind(FILE *file
)
94 fseek(file
, 0, SEEK_SET
);
96 void clearerr(FILE *file
)
101 int fgetpos(FILE *file
, fpos_t *pos
)
103 if (!file
|| !pos
) return EOF
;
105 long int position
= lseek(file
->fd
, 0, SEEK_CUR
);
114 int fsetpos(FILE *file
, const fpos_t *pos
)
116 if (!file
|| !pos
) return EOF
;
118 if (lseek(file
->fd
, *pos
, SEEK_SET
) == (off_t
)-1) return -1;
122 int fgetc(FILE *file
)
124 if (!file
) return EOF
;
126 int size
= read(file
->fd
, &c
, 1);
129 file
->error
= ERROR_EOF
;
134 file
->error
= ERROR_ERROR
;
139 char *fgets(char *str
, int num
, FILE *file
)
144 char c
= fgetc(file
);
145 if ((c
== EOF
) && ferror(file
)) return 0;
146 if ((c
== EOF
) && (n
== 0))
150 else if ((c
== EOF
) || (c
== '\n') || (c
== 0))
164 int fscanf(FILE *file
, const char *fmt
, ...)
168 size_t fread(void *ptr
, size_t size
, size_t count
, FILE *file
)
171 int bytecount
= read(file
->fd
, ptr
, size
* count
);
174 file
->error
= ERROR_ERROR
;
177 if (bytecount
!= (int)(size
* count
))
179 file
->error
= ERROR_EOF
;
184 int fputc(int c
, FILE *file
)
186 if (!file
) return EOF
;
187 if (file
->append
) lseek(file
->fd
, 0, SEEK_END
);
188 int size
= write(file
->fd
, &c
, 1);
191 file
->error
= ERROR_EOF
;
196 file
->error
= ERROR_ERROR
;
201 int fputs(const char *s
, FILE *file
)
203 if (!file
) return EOF
;
204 if (file
->append
) lseek(file
->fd
, 0, SEEK_END
);
205 int size
= write(file
->fd
, s
, strlen(s
));
208 file
->error
= ERROR_ERROR
;
213 int vfprintf(FILE *file
, const char *fmt
, va_list args
)
215 if (!file
) return EOF
;
216 if (file
->append
) lseek(file
->fd
, 0, SEEK_END
);
217 // FIXME: Greater length?
219 vsnprintf(buffer
, 1024, fmt
, args
);
221 int written
= write(file
->fd
, buffer
, strlen(buffer
));
224 file
->error
= ERROR_ERROR
;
229 int fprintf(FILE *file
, const char *fmt
, ...)
231 if (!file
) return EOF
;
232 if (file
->append
) lseek(file
->fd
, 0, SEEK_END
);
233 // FIXME: Greater length?
237 vsnprintf(buffer
, 1024, fmt
, args
);
240 int written
= write(file
->fd
, buffer
, strlen(buffer
));
243 file
->error
= ERROR_ERROR
;
248 size_t fwrite(const void *ptr
, size_t size
, size_t count
, FILE *file
)
250 if (!file
) return EOF
;
251 if (file
->append
) lseek(file
->fd
, 0, SEEK_END
);
252 int written
= write(file
->fd
, ptr
, size
* count
);
253 if (written
== -1) return EOF
;
262 char *tmpnam(char *s
)
268 int ungetc(int character
, FILE *file
)
273 int rename(const char *oldname
, const char *newname
)
277 int remove(const char *filename
)
282 int printf(const char *fmt
, ...)
286 int status
= vfprintf(stdout
, fmt
, args
);
290 int puts(const char *s
)
296 int snprintf(char *buf
, size_t n
, const char *fmt
, ...)
300 int retval
= vsnprintf(buf
, n
, fmt
, args
);
304 int sprintf(char *buf
, const char *fmt
, ...)
308 int retval
= vsprintf(buf
, fmt
, args
);
313 inline void write_char(char **buf
, const char **fmt
, char c
)
320 static uint32_t write_integer(char **buf
, size_t n
, int i
, int base
, int prefix
, int leftjustify
, int forcesign
, int insertspace
, int zeros
, int minimumwidth
)
330 int numberlength
= 0;
333 tmp
[numberlength
] = (i
% base
) + '0';
335 tmp
[numberlength
] = 0;
339 if (prefix
&& (base
== 8))
341 tmp
[numberlength
] = '0';
343 tmp
[numberlength
] = 0;
345 int needed
= numberlength
;
346 if (forcesign
|| insertspace
|| negative
) needed
++;
348 uint32_t written
= 0;
349 if (leftjustify
|| ((minimumwidth
<= needed
) && !zeros
))
354 write_char(buf
, 0, '-');
356 if (written
== n
) return n
;
358 else if (insertspace
)
360 write_char(buf
, 0, ' ');
362 if (written
== n
) return n
;
366 write_char(buf
, 0, '+');
368 if (written
== n
) return n
;
371 for (idx
= 0; idx
< numberlength
; idx
++)
373 write_char(buf
, 0, tmp
[numberlength
- idx
- 1]);
375 if (written
== n
) return n
;
378 if (minimumwidth
> needed
)
380 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
382 write_char(buf
, 0, ' ');
384 if (written
== n
) return n
;
399 write_char(buf
, 0, '-');
401 if (written
== n
) return n
;
403 else if (insertspace
)
405 write_char(buf
, 0, ' ');
407 if (written
== n
) return n
;
411 write_char(buf
, 0, '+');
413 if (written
== n
) return n
;
417 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
419 write_char(buf
, 0, '0');
421 if (written
== n
) return n
;
423 for (idx
= 0; idx
< numberlength
; idx
++)
425 write_char(buf
, 0, tmp
[numberlength
- idx
- 1]);
427 if (written
== n
) return n
;
433 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
435 write_char(buf
, 0, ' ');
437 if (written
== n
) return n
;
441 write_char(buf
, 0, '-');
443 if (written
== n
) return n
;
445 else if (insertspace
)
447 write_char(buf
, 0, ' ');
449 if (written
== n
) return n
;
453 write_char(buf
, 0, '+');
455 if (written
== n
) return n
;
457 for (idx
= 0; idx
< numberlength
; idx
++)
459 write_char(buf
, 0, tmp
[numberlength
- idx
- 1]);
461 if (written
== n
) return n
;
468 static char digits
[] = "0123456789abcdef";
469 static char digits_capital
[] = "0123456789ABCDEF";
471 static uint32_t write_unsigned_integer(char **buf
, size_t n
, unsigned int i
,
472 int base
, int prefix
, int capital
, int leftjustify
, int forcesign
, int insertspace
, int zeros
, int minimumwidth
)
476 write_char(buf
, 0, '0');
481 uint32_t written
= 0;
482 int numberlength
= 0;
487 tmp
[numberlength
] = digits_capital
[i
% base
];
491 tmp
[numberlength
] = digits
[i
% base
];
494 tmp
[numberlength
] = 0;
497 if (prefix
&& (base
== 8))
499 tmp
[numberlength
] = '0';
501 tmp
[numberlength
] = 0;
503 else if (prefix
&& (base
== 16) && !zeros
)
505 tmp
[numberlength
] = capital
?'X':'x';
507 tmp
[numberlength
] = '0';
509 tmp
[numberlength
] = 0;
512 else if (prefix
&& (base
== 16))
517 if (written
== n
) return n
;
518 **buf
= capital
?'X':'x';
521 if (written
== n
) return n
;
524 int needed
= numberlength
;
525 if (forcesign
|| insertspace
) needed
++;
527 if (leftjustify
|| ((minimumwidth
<= needed
) && !zeros
))
535 if (written
== n
) return n
;
542 if (written
== n
) return n
;
545 for (idx
= 0; idx
< numberlength
; idx
++)
547 **buf
= tmp
[numberlength
- idx
- 1];
550 if (written
== n
) return n
;
553 if (minimumwidth
> needed
)
555 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
560 if (written
== n
) return n
;
578 if (written
== n
) return n
;
585 if (written
== n
) return n
;
589 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
594 if (written
== n
) return n
;
596 for (idx
= 0; idx
< numberlength
; idx
++)
598 **buf
= tmp
[numberlength
- idx
- 1];
601 if (written
== n
) return n
;
607 for (idx
= 0; idx
< minimumwidth
- needed
; idx
++)
612 if (written
== n
) return n
;
619 if (written
== n
) return n
;
626 if (written
== n
) return n
;
628 for (idx
= 0; idx
< numberlength
; idx
++)
630 **buf
= tmp
[numberlength
- idx
- 1];
633 if (written
== n
) return n
;
640 static uint32_t parse_expression(char **buf
, const char **fmt
, size_t n
, size_t oldn
, va_list *ap
)
642 if (n
== 0) return 0;
649 int minimumwidth
= 0;
650 int minimumwidth2
= 0;
672 minimumwidth
= minimumwidth
* 10;
675 minimumwidth
= minimumwidth
* 10 + (**fmt
- '0');
678 minimumwidth2
= va_arg(*ap
, int);
687 write_char(buf
, fmt
, '%');
690 write_char(buf
, fmt
, va_arg(*ap
, char));
697 if (length
== 0) i
= va_arg(*ap
, int);
698 else if (length
== -1) i
= (short)va_arg(*ap
, int);
699 else if (length
== -2) i
= (char)va_arg(*ap
, int);
700 else i
= va_arg(*ap
, int);
702 if (minimumwidth2
) minimumwidth
= minimumwidth2
;
703 return write_integer(buf
, n
, i
, 10, 0, leftjustify
, forcesign
, insertspace
, zeros
, minimumwidth
);
709 if (length
== 0) i
= va_arg(*ap
, int);
710 else if (length
== -1) i
= (short)va_arg(*ap
, int);
711 else if (length
== -2) i
= (char)va_arg(*ap
, int);
712 else i
= va_arg(*ap
, int);
714 if (minimumwidth2
) minimumwidth
= minimumwidth2
;
715 return write_integer(buf
, n
, i
, 8, prefix
, leftjustify
, forcesign
, insertspace
, zeros
, minimumwidth
);
720 char *s
= va_arg(*ap
, char*);
721 uint32_t written
= 0;
722 while (*s
&& written
< n
)
735 if (length
== 0) i
= va_arg(*ap
, int);
736 else if (length
== -1) i
= (unsigned short)va_arg(*ap
, int);
737 else if (length
== -2) i
= (unsigned char)va_arg(*ap
, int);
738 else i
= va_arg(*ap
, int);
740 if (minimumwidth2
) minimumwidth
= minimumwidth2
;
741 return write_unsigned_integer(buf
, n
, i
, 10, 0, 0, leftjustify
, forcesign
, insertspace
, zeros
, minimumwidth
);
747 if (length
== 0) i
= va_arg(*ap
, int);
748 else if (length
== -1) i
= (unsigned short)va_arg(*ap
, int);
749 else if (length
== -2) i
= (unsigned char)va_arg(*ap
, int);
750 else i
= va_arg(*ap
, int);
752 if (minimumwidth2
) minimumwidth
= minimumwidth2
;
753 return write_unsigned_integer(buf
, n
, i
, 16, prefix
, 0, leftjustify
, forcesign
, insertspace
, zeros
, minimumwidth
);
759 if (length
== 0) i
= va_arg(*ap
, int);
760 else if (length
== -1) i
= (unsigned short)va_arg(*ap
, int);
761 else if (length
== -2) i
= (unsigned char)va_arg(*ap
, int);
762 else i
= va_arg(*ap
, int);
764 if (minimumwidth2
) minimumwidth
= minimumwidth2
;
765 return write_unsigned_integer(buf
, n
, i
, 16, prefix
, 1, leftjustify
, forcesign
, insertspace
, zeros
, minimumwidth
);
770 unsigned int i
= va_arg(*ap
, unsigned int);
771 return write_unsigned_integer(buf
, n
, i
, 16, 1, 0, 0, 0, 0, 1, 10);
776 int *target
= va_arg(*ap
, int*);
789 int vsnprintf(char *buf
, size_t n
, const char *fmt
, va_list arg
)
791 if (n
== 0) return 0;
792 uint32_t written
= 0;
793 while (*fmt
&& (written
< n
))
800 written
+= parse_expression(&buf
, &fmt
, n
- written
, n
, &arg
);
822 int vsprintf(char *buf
, const char *fmt
, va_list arg
)
824 return vsnprintf(buf
, 0xFFFFFFFF, fmt
, arg
);
827 int asprintf(char **buf
, const char *fmt
, ...)
831 int retval
= vasprintf(buf
, fmt
, args
);
835 int vasprintf(char **buf
, const char *fmt
, va_list arg
)
837 va_list tmparg
= arg
;
838 char *buffer
= malloc(16);
839 if (!buffer
) return -1;
841 int written
= vsnprintf(buffer
, 16, fmt
, arg
);
842 while (written
== buffersize
)
844 buffer
= realloc(buffer
, buffersize
+ 16);
845 if (!buffer
) return -1;
847 written
= vsnprintf(buffer
, buffersize
, fmt
, tmparg
);