First try in keyboard driver
[incOS.git] / programs / libc / stdio.c
blobf3529d6d61678c605fcd5eb63c337dd63ea1d20d
1 /*
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.
22 #include <stdio.h>
23 #include <kernel.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdlib.h>
28 #define ERROR_EOF 1
29 #define ERROR_ERROR 2
31 struct FILE
33 int fd;
34 int append;
35 int error;
38 FILE *stderr = 0;
39 FILE *stdout = 0;
40 FILE *stdin = 0;
42 FILE *fopen(const char *filename, const char *mode)
44 // Open file
45 int openmode = 0;
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));
55 file->fd = fd;
56 if (strchr(mode, 'a')) file->append = 1;
57 return file;
59 int fclose(FILE *file)
61 if (!file) return EOF;
62 close(file->fd);
63 free(file);
64 return 0;
66 FILE *freopen(const char *filename, const char *mode, FILE *file)
68 if (fclose(file) == EOF) return 0;
69 return fopen(filename, mode);
71 int feof(FILE *file)
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;
82 file->error = 0;
83 if (lseek(file->fd, offset, origin) == (off_t)-1) return EOF;
84 return 0;
86 long int ftell(FILE *file)
88 if (!file) return EOF;
89 long int pos = lseek(file->fd, 0, SEEK_CUR);
90 return pos;
92 void rewind(FILE *file)
94 fseek(file, 0, SEEK_SET);
96 void clearerr(FILE *file)
98 file->error = 0;
101 int fgetpos(FILE *file, fpos_t *pos)
103 if (!file || !pos) return EOF;
105 long int position = lseek(file->fd, 0, SEEK_CUR);
106 if (position == -1)
108 *pos = 0;
109 return EOF;
111 *pos = position;
112 return 0;
114 int fsetpos(FILE *file, const fpos_t *pos)
116 if (!file || !pos) return EOF;
117 file->error = 0;
118 if (lseek(file->fd, *pos, SEEK_SET) == (off_t)-1) return -1;
119 return 0;
122 int fgetc(FILE *file)
124 if (!file) return EOF;
125 char c = 0;
126 int size = read(file->fd, &c, 1);
127 if (size == 0)
129 file->error = ERROR_EOF;
130 return EOF;
132 else if (size == -1)
134 file->error = ERROR_ERROR;
135 return EOF;
137 return c;
139 char *fgets(char *str, int num, FILE *file)
141 int n = 0;
142 while (n < num)
144 char c = fgetc(file);
145 if ((c == EOF) && ferror(file)) return 0;
146 if ((c == EOF) && (n == 0))
148 return 0;
150 else if ((c == EOF) || (c == '\n') || (c == 0))
152 str[n] = 0;
153 return str;
155 else
157 str[n] = c;
159 n++;
161 str[n - 1] = 0;
162 return str;
164 int fscanf(FILE *file, const char *fmt, ...)
166 return -1;
168 size_t fread(void *ptr, size_t size, size_t count, FILE *file)
170 if (!file) return 0;
171 int bytecount = read(file->fd, ptr, size * count);
172 if (bytecount == -1)
174 file->error = ERROR_ERROR;
175 return 0;
177 if (bytecount != (int)(size * count))
179 file->error = ERROR_EOF;
181 return bytecount;
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);
189 if (size == 0)
191 file->error = ERROR_EOF;
192 return EOF;
194 else if (size == -1)
196 file->error = ERROR_ERROR;
197 return EOF;
199 return c;
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));
206 if (size == -1)
208 file->error = ERROR_ERROR;
209 return EOF;
211 return size;
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?
218 char buffer[1024];
219 vsnprintf(buffer, 1024, fmt, args);
221 int written = write(file->fd, buffer, strlen(buffer));
222 if (written == -1)
224 file->error = ERROR_ERROR;
225 return EOF;
227 return written;
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?
234 char buffer[1024];
235 va_list args;
236 va_start(args, fmt);
237 vsnprintf(buffer, 1024, fmt, args);
238 va_end(args);
240 int written = write(file->fd, buffer, strlen(buffer));
241 if (written == -1)
243 file->error = ERROR_ERROR;
244 return EOF;
246 return written;
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;
254 return written;
257 FILE *tmpfile(void)
259 // TODO
260 return 0;
262 char *tmpnam(char *s)
264 // TODO
265 return s;
268 int ungetc(int character, FILE *file)
270 return EOF;
273 int rename(const char *oldname, const char *newname)
275 return -1;
277 int remove(const char *filename)
279 return -1;
282 int printf(const char *fmt, ...)
284 va_list args;
285 va_start(args, fmt);
286 int status = vfprintf(stdout, fmt, args);
287 va_end(args);
288 return status;
290 int puts(const char *s)
292 printf("%s\n", s);
293 return 0;
296 int snprintf(char *buf, size_t n, const char *fmt, ...)
298 va_list args;
299 va_start(args, fmt);
300 int retval = vsnprintf(buf, n, fmt, args);
301 va_end(args);
302 return retval;
304 int sprintf(char *buf, const char *fmt, ...)
306 va_list args;
307 va_start(args, fmt);
308 int retval = vsprintf(buf, fmt, args);
309 va_end(args);
310 return retval;
313 inline void write_char(char **buf, const char **fmt, char c)
315 **buf = c;
316 (*buf)++;
317 if (fmt) (*fmt)++;
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)
322 int negative = 0;
323 if (i < 0)
325 negative = 1;
326 i = -i;
328 char tmp[20];
329 tmp[0] = 0;
330 int numberlength = 0;
333 tmp[numberlength] = (i % base) + '0';
334 numberlength++;
335 tmp[numberlength] = 0;
336 i /= base;
338 while (i);
339 if (prefix && (base == 8))
341 tmp[numberlength] = '0';
342 numberlength++;
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))
351 // Just print number
352 if (negative)
354 write_char(buf, 0, '-');
355 written++;
356 if (written == n) return n;
358 else if (insertspace)
360 write_char(buf, 0, ' ');
361 written++;
362 if (written == n) return n;
364 else if (forcesign)
366 write_char(buf, 0, '+');
367 written++;
368 if (written == n) return n;
370 int idx;
371 for (idx = 0; idx < numberlength; idx++)
373 write_char(buf, 0, tmp[numberlength - idx - 1]);
374 written++;
375 if (written == n) return n;
378 if (minimumwidth > needed)
380 for (idx = 0; idx < minimumwidth - needed; idx++)
382 write_char(buf, 0, ' ');
383 written++;
384 if (written == n) return n;
386 return minimumwidth;
388 else
390 return needed;
393 else
395 if (zeros)
397 if (negative)
399 write_char(buf, 0, '-');
400 written++;
401 if (written == n) return n;
403 else if (insertspace)
405 write_char(buf, 0, ' ');
406 written++;
407 if (written == n) return n;
409 else if (forcesign)
411 write_char(buf, 0, '+');
412 written++;
413 if (written == n) return n;
416 int idx;
417 for (idx = 0; idx < minimumwidth - needed; idx++)
419 write_char(buf, 0, '0');
420 written++;
421 if (written == n) return n;
423 for (idx = 0; idx < numberlength; idx++)
425 write_char(buf, 0, tmp[numberlength - idx - 1]);
426 written++;
427 if (written == n) return n;
430 else
432 int idx;
433 for (idx = 0; idx < minimumwidth - needed; idx++)
435 write_char(buf, 0, ' ');
436 written++;
437 if (written == n) return n;
439 if (negative)
441 write_char(buf, 0, '-');
442 written++;
443 if (written == n) return n;
445 else if (insertspace)
447 write_char(buf, 0, ' ');
448 written++;
449 if (written == n) return n;
451 else if (forcesign)
453 write_char(buf, 0, '+');
454 written++;
455 if (written == n) return n;
457 for (idx = 0; idx < numberlength; idx++)
459 write_char(buf, 0, tmp[numberlength - idx - 1]);
460 written++;
461 if (written == n) return n;
464 return minimumwidth;
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)
474 if (!i)
476 write_char(buf, 0, '0');
477 return 1;
479 char tmp[20];
480 tmp[0] = 0;
481 uint32_t written = 0;
482 int numberlength = 0;
483 while (i)
485 if (capital)
487 tmp[numberlength] = digits_capital[i % base];
489 else
491 tmp[numberlength] = digits[i % base];
493 numberlength++;
494 tmp[numberlength] = 0;
495 i /= base;
497 if (prefix && (base == 8))
499 tmp[numberlength] = '0';
500 numberlength++;
501 tmp[numberlength] = 0;
503 else if (prefix && (base == 16) && !zeros)
505 tmp[numberlength] = capital?'X':'x';
506 numberlength++;
507 tmp[numberlength] = '0';
508 numberlength++;
509 tmp[numberlength] = 0;
512 else if (prefix && (base == 16))
514 **buf = '0';
515 (*buf)++;
516 written++;
517 if (written == n) return n;
518 **buf = capital?'X':'x';
519 (*buf)++;
520 written++;
521 if (written == n) return n;
522 minimumwidth -= 2;
524 int needed = numberlength;
525 if (forcesign || insertspace) needed++;
527 if (leftjustify || ((minimumwidth <= needed) && !zeros))
529 // Just print number
530 if (insertspace)
532 **buf = ' ';
533 (*buf)++;
534 written++;
535 if (written == n) return n;
537 else if (forcesign)
539 **buf = '+';
540 (*buf)++;
541 written++;
542 if (written == n) return n;
544 int idx;
545 for (idx = 0; idx < numberlength; idx++)
547 **buf = tmp[numberlength - idx - 1];
548 (*buf)++;
549 written++;
550 if (written == n) return n;
553 if (minimumwidth > needed)
555 for (idx = 0; idx < minimumwidth - needed; idx++)
557 **buf = ' ';
558 (*buf)++;
559 written++;
560 if (written == n) return n;
562 return minimumwidth;
564 else
566 return needed;
569 else
571 if (zeros)
573 if (insertspace)
575 **buf = ' ';
576 (*buf)++;
577 written++;
578 if (written == n) return n;
580 else if (forcesign)
582 **buf = '+';
583 (*buf)++;
584 written++;
585 if (written == n) return n;
588 int idx;
589 for (idx = 0; idx < minimumwidth - needed; idx++)
591 **buf = '0';
592 (*buf)++;
593 written++;
594 if (written == n) return n;
596 for (idx = 0; idx < numberlength; idx++)
598 **buf = tmp[numberlength - idx - 1];
599 (*buf)++;
600 written++;
601 if (written == n) return n;
604 else
606 int idx;
607 for (idx = 0; idx < minimumwidth - needed; idx++)
609 **buf = ' ';
610 (*buf)++;
611 written++;
612 if (written == n) return n;
614 if (insertspace)
616 **buf = ' ';
617 (*buf)++;
618 written++;
619 if (written == n) return n;
621 else if (forcesign)
623 **buf = '+';
624 (*buf)++;
625 written++;
626 if (written == n) return n;
628 for (idx = 0; idx < numberlength; idx++)
630 **buf = tmp[numberlength - idx - 1];
631 (*buf)++;
632 written++;
633 if (written == n) return n;
636 return minimumwidth;
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;
644 int leftjustify = 0;
645 int forcesign = 0;
646 int prefix = 0;
647 int zeros = 0;
648 int insertspace = 0;
649 int minimumwidth = 0;
650 int minimumwidth2 = 0;
651 int length = 0;
652 while (**fmt)
654 switch (**fmt)
656 case '-':
657 leftjustify = 1;
658 break;
659 case '+':
660 forcesign = 1;
661 break;
662 case '#':
663 prefix = 1;
664 break;
665 case ' ':
666 insertspace = 1;
667 break;
668 case '0':
669 if (!minimumwidth)
670 zeros = 1;
671 else
672 minimumwidth = minimumwidth * 10;
673 break;
674 case '1' ... '9':
675 minimumwidth = minimumwidth * 10 + (**fmt - '0');
676 break;
677 case '*':
678 minimumwidth2 = va_arg(*ap, int);
679 break;
680 case 'h':
681 length--;
682 break;
683 case 'l':
684 length++;
685 break;
686 case '%':
687 write_char(buf, fmt, '%');
688 return 1;
689 case 'c':
690 write_char(buf, fmt, va_arg(*ap, char));
691 return 1;
692 case 'd':
693 case 'i':
695 (*fmt)++;
696 int i = 0;
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);
705 case 'o':
707 (*fmt)++;
708 int i = 0;
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);
717 case 's':
719 (*fmt)++;
720 char *s = va_arg(*ap, char*);
721 uint32_t written = 0;
722 while (*s && written < n)
724 **buf = *s;
725 (*buf)++;
726 written++;
727 s++;
729 return written;
731 case 'u':
733 (*fmt)++;
734 unsigned int i = 0;
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);
743 case 'x':
745 (*fmt)++;
746 unsigned int i = 0;
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);
755 case 'X':
757 (*fmt)++;
758 unsigned int i = 0;
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);
767 case 'p':
769 (*fmt)++;
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);
773 case 'n':
775 (*fmt)++;
776 int *target = va_arg(*ap, int*);
777 *target = oldn - n;
778 return 0;
780 default:
781 return 0;
783 (*fmt)++;
786 return 0;
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))
795 switch (*fmt)
797 case '%':
798 fmt++;
799 // TODO
800 written += parse_expression(&buf, &fmt, n - written, n, &arg);
801 break;
802 default:
803 *buf = *fmt;
804 buf++;
805 fmt++;
806 written++;
807 break;
810 if (written < n)
812 *buf = 0;
813 written++;
815 else
817 buf--;
818 *buf = 0;
820 return written;
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, ...)
829 va_list args;
830 va_start(args, fmt);
831 int retval = vasprintf(buf, fmt, args);
832 va_end(args);
833 return retval;
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;
840 int buffersize = 16;
841 int written = vsnprintf(buffer, 16, fmt, arg);
842 while (written == buffersize)
844 buffer = realloc(buffer, buffersize + 16);
845 if (!buffer) return -1;
846 buffersize += 16;
847 written = vsnprintf(buffer, buffersize, fmt, tmparg);
849 *buf = buffer;
850 return written;