mescc: Basic printf support.
* module/mes/libc-i386.mes (i386:va-arg): New function. * module/mes/libc-i386.scm (mes): Export it. * module/mes/libc.mes (printf): New function. (libc): Add it. * libc/include/stdio.h: New file. * module/language/c99/compiler.mes (c99-input->ast): Add libc/include to include path. (ast-info): Handle (skip) ellipsis in function declaration.
This commit is contained in:
parent
b811cc0c50
commit
4e0042cae6
|
@ -0,0 +1,6 @@
|
|||
#ifndef __STDIO_H
|
||||
#define __STDIO_H 1
|
||||
|
||||
int printf (char const* format, ...);
|
||||
|
||||
#endif // __STDIO_H
|
69
libc/mlibc.c
69
libc/mlibc.c
|
@ -331,6 +331,75 @@ atoi (char const *s)
|
|||
}
|
||||
return i * sign;
|
||||
}
|
||||
|
||||
int
|
||||
printf (char const* format, ...)
|
||||
{
|
||||
int va_arg = 0;
|
||||
int va;
|
||||
char const *p = format;
|
||||
while (*p)
|
||||
if (*p != '%')
|
||||
putchar (*p++);
|
||||
else
|
||||
{
|
||||
p++;
|
||||
char c = *p;
|
||||
switch (c)
|
||||
{
|
||||
case '%': {putchar (*p); break;}
|
||||
case 'c':
|
||||
{
|
||||
asm (
|
||||
"mov -0xc(%%ebp),%%eax\n\t"
|
||||
"shl $0x2,%%eax\n\t"
|
||||
"add %%ebp,%%eax\n\t"
|
||||
"add $0xc,%%eax\n\t"
|
||||
"mov (%%eax),%%eax\n\t"
|
||||
//"mov %%eax,%0\n\t"
|
||||
: "=va" (va)
|
||||
: //no inputs ""
|
||||
);
|
||||
putchar ((char)va);
|
||||
va_arg++;
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
asm (
|
||||
"mov -0xc(%%ebp),%%eax\n\t"
|
||||
"shl $0x2,%%eax\n\t"
|
||||
"add %%ebp,%%eax\n\t"
|
||||
"add $0xc,%%eax\n\t"
|
||||
"mov (%%eax),%%eax\n\t"
|
||||
//"mov %%eax,%0\n\t"
|
||||
: "=va" (va)
|
||||
: //no inputs ""
|
||||
);
|
||||
puts (itoa ((int)va));
|
||||
va_arg++;
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
asm (
|
||||
"mov -0xc(%%ebp),%%eax\n\t"
|
||||
"shl $0x2,%%eax\n\t"
|
||||
"add %%ebp,%%eax\n\t"
|
||||
"add $0xc,%%eax\n\t"
|
||||
"mov (%%eax),%%eax\n\t"
|
||||
//"mov %%eax,%0\n\t"
|
||||
: "=va" (va)
|
||||
: //no inputs ""
|
||||
);
|
||||
puts ((char*)va);
|
||||
va_arg++;
|
||||
break;
|
||||
}
|
||||
default: putchar (*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
char itoa_buf[10];
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
|
||||
(define (c99-input->ast)
|
||||
(parse-c99
|
||||
#:inc-dirs (cons* "." "libc" "src" "out" "out/src" (string-split (getenv "C_INCLUDE_PATH") #\:))
|
||||
#:inc-dirs (cons* "." "libc/include" "libc" "src" "out" "out/src" (string-split (getenv "C_INCLUDE_PATH") #\:))
|
||||
#:cpp-defs `(
|
||||
"POSIX=0"
|
||||
"_POSIX_SOURCE=0"
|
||||
|
@ -872,9 +872,11 @@
|
|||
(define (test->text test)
|
||||
(let ((value (pmatch test
|
||||
(0 0)
|
||||
((p-expr (char ,value)) (char->integer (car (string->list value))))
|
||||
((p-expr (ident ,constant)) (assoc-ref (.constants info) constant))
|
||||
((p-expr (fixed ,value)) (cstring->number value))
|
||||
((neg (p-expr (fixed ,value))) (- (cstring->number value))))))
|
||||
((neg (p-expr (fixed ,value))) (- (cstring->number value)))
|
||||
(_ (error "case test: unsupported: " test)))))
|
||||
(lambda (n)
|
||||
(append (wrap-as (i386:accu-cmp-value value))
|
||||
(jump-z (+ (length (text->list (jump 0)))
|
||||
|
@ -1730,6 +1732,10 @@
|
|||
(let ((types (.types info)))
|
||||
(clone info #:types (cons (cons name (assoc-ref types type)) types))))
|
||||
|
||||
;; printf (char const* format, ...)
|
||||
((decl (decl-spec-list (type-spec (fixed-type ,type))) (init-declr-list (init-declr (ftn-declr (ident ,name) (param-list ,param-list (ellipsis))))))
|
||||
info)
|
||||
|
||||
((decl (decl-spec-list (stor-spec (typedef)) ,type) ,name)
|
||||
(format (current-error-port) "SKIP: typedef=~s\n" o)
|
||||
info)
|
||||
|
|
|
@ -140,6 +140,17 @@
|
|||
" 0x50" ; push %eax
|
||||
))
|
||||
|
||||
(define (i386:va-arg)
|
||||
(string-append ".byte"
|
||||
" 0x8b 0x45 0xfc" ; mov -<0x4>(%ebp),%eax :va_arg
|
||||
" 0xc1 0xe0 0x2" ; shl $0x2,%eax
|
||||
" 0x01 0xe8" ; add %ebp,%eax
|
||||
" 0x83 0xc0 0xc" ; add $0xc,%eax
|
||||
" 0x8b 0x00" ; mov (%eax),%eax
|
||||
" 0x89 0x45 0xf8" ; mov %eax,-0x8(%ebp) :va
|
||||
" 0x50" ; push %eax
|
||||
))
|
||||
|
||||
(define i386:libc
|
||||
(list
|
||||
(cons "exit" (list i386:exit))
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
(define-module (mes libc-i386)
|
||||
#:export (i386:libc
|
||||
i386:_start))
|
||||
i386:_start
|
||||
i386:va-arg))
|
||||
|
||||
(include-from-path "mes/libc-i386.mes")
|
||||
|
|
|
@ -351,6 +351,38 @@ getenv (char const* s)
|
|||
}
|
||||
" parse-c99))
|
||||
|
||||
(define (printf)
|
||||
(format (current-error-port) "parsing: printf\n")
|
||||
(let ((va-arg (i386:va-arg)))
|
||||
(with-input-from-string
|
||||
(string-append "
|
||||
int
|
||||
printf (char const* format, int va_args)
|
||||
{
|
||||
int va_arg = 0;
|
||||
int va;
|
||||
char *p = format;
|
||||
while (*p)
|
||||
if (*p != '%')
|
||||
putchar (*p++);
|
||||
else
|
||||
{
|
||||
p++;
|
||||
char c = *p;
|
||||
switch (c)
|
||||
{
|
||||
case '%': {putchar (*p); break;}
|
||||
case 'c': {asm (\"" va-arg "\"); putchar ((char)va); va_arg++; break;}
|
||||
case 'd': {asm (\"" va-arg "\"); puts (itoa (va)); va_arg++; break;}
|
||||
case 's': {asm (\"" va-arg "\"); puts ((char*)va); va_arg++; break;}
|
||||
default: putchar (*p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
") parse-c99)))
|
||||
|
||||
(define libc
|
||||
(list
|
||||
strlen
|
||||
|
@ -370,4 +402,5 @@ getenv (char const* s)
|
|||
realloc
|
||||
strncmp
|
||||
c:getenv
|
||||
printf
|
||||
))
|
||||
|
|
Loading…
Reference in New Issue