mescc: Basic printf support.
authorJan Nieuwenhuizen <janneke@gnu.org>
Tue, 2 May 2017 15:00:07 +0000 (17:00 +0200)
committerJan Nieuwenhuizen <janneke@gnu.org>
Tue, 2 May 2017 15:00:07 +0000 (17:00 +0200)
* 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.

libc/include/stdio.h [new file with mode: 0644]
libc/mlibc.c
module/language/c99/compiler.mes
module/mes/libc-i386.mes
module/mes/libc-i386.scm
module/mes/libc.mes

diff --git a/libc/include/stdio.h b/libc/include/stdio.h
new file mode 100644 (file)
index 0000000..52a2c18
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __STDIO_H
+#define __STDIO_H 1
+
+int printf (char const* format, ...);
+
+#endif // __STDIO_H
index 98bcd9dd3a7312781a87f3cfd8e7996d2a7f695a..450d879d98b99f536f53be6608c366202ec1d089 100644 (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];
index 00033fcd1d02dbadc4ef88ba8a69c8f4e057663a..2a5c9350e72b759372716e75968277733fafc3ee 100644 (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"
   (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)))
          (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)
index eb70a900e05986c1419d2138cc47077fcbe075ef..905caeac5f1e4231add7933f5e62947edf981661 100644 (file)
                 " 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))
index 6e5fabb190b3664a8508140c1695f17ae299a228..999befb5898297cd01aa5495b3e22678c1c9f992 100644 (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")
index 15d73bc4c7666a2b1581e614e574ab4ce194afee..a7b302ed047404add50a390052f4e46d0199fe7c 100644 (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
    ))