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:
Jan Nieuwenhuizen 2017-05-02 17:00:07 +02:00
parent b811cc0c50
commit 4e0042cae6
6 changed files with 129 additions and 3 deletions

6
libc/include/stdio.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __STDIO_H
#define __STDIO_H 1
int printf (char const* format, ...);
#endif // __STDIO_H

View File

@ -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];

View File

@ -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)

View File

@ -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))

View File

@ -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")

View File

@ -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
))