shithub: fnt

Download patch

ref: 207f8c591b3e831f4a35185b99482cfb34fccf4b
parent: 74504c05e0be45260076e95e8e25cfc39f0ea6cf
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Jun 19 13:25:43 EDT 2024

use Bprint; finish ctxpushrange/ctxpoprange/ctxreadn

--- a/otf.rkt
+++ b/otf.rkt
@@ -66,6 +66,9 @@
 (define (field-cond f)
   (assoc 'cond (field-attrs f)))
 
+(define (field-ptr f)
+  (assoc 'ptr (field-attrs f)))
+
 (define (block stmt lst)
   (if (= (length lst) 1) (list* stmt lst) (list (string-append stmt "{") lst "}")))
 
@@ -76,7 +79,7 @@
      (block (~a "if(" (string-join (map (λ (n) (~a "v->" ref " " op " " n)) n) " || ") ")")
             (indent (flatten lst)))]))
 
-(define (field-fprint-c f)
+(define (field-print-c f)
   (define t (field-type f))
   (define count (field-count f))
   (define end (and count (if (cmplx? t) (~a "v->" (cadr count)) (cadr count))))
@@ -84,9 +87,9 @@
   (define fixed-array (and basic-array (number? end)))
   (define array-index (if (field-count f) "[i]" ""))
   (define verb (if (type? t) (if (field-verb f) (cadr (field-verb f)) (type-verb t)) ""))
-  (define fprint-index
+  (define print-index
     (if basic-array
-        (~a "fprint(f, \"%*s%s[%d]: "
+        (~a "Bprint(f, \"%*s%s[%d]: "
             verb
             "\\n\", indent, \"\", \""
             (field-name f)
@@ -94,17 +97,17 @@
             (field-name f)
             array-index
             ");")
-        (~a "fprint(f, \"%*s%s[%d]:\\n\", indent, \"\", \"" (field-name f) "\", i);")))
+        (~a "Bprint(f, \"%*s%s[%d]:\\n\", indent, \"\", \"" (field-name f) "\", i);")))
   (define array-loop
     (if count
         (λ (lst)
           (block (~a "for(int i = 0; i < " (if fixed-array "" "v->") (cadr count) "; i++)")
-                 (indent (list* fprint-index (if basic-array empty lst)))))
+                 (indent (list* print-index (if basic-array empty lst)))))
         identity))
   (define lst
     (list
      (if (type? t)
-         (~a "fprint(f, \"%*s%s: "
+         (~a "Bprint(f, \"%*s%s: "
              verb
              "\\n\", indent, \"\", \""
              (field-name f)
@@ -112,7 +115,7 @@
              (field-name f)
              array-index
              ");")
-         (~a "fprint_" (cmplx-name t) "(f, indent+indentΔ, &v->" (field-name f) array-index ");"))))
+         (~a "print_" (cmplx-name t) "(f, indent+indentΔ, &v->" (field-name f) array-index ");"))))
   (if (field-unused? f) empty (wrap-cond-c (field-cond f) (array-loop lst))))
 
 (define (invert-c op)
@@ -289,10 +292,10 @@
                     (~a "}"))
               (list (~a "")
                     (~a "void")
-                    (~a "fprint_" (cmplx-name c) "(int f, int indent, " (cmplx-name c) " *v)")
+                    (~a "print_" (cmplx-name c) "(Biobuf *f, int indent, " (cmplx-name c) " *v)")
                     (~a "{")
-                    (indent (flatten (map field-fprint-c (cmplx-fields c))))
-                    (indent (filter-extra (cmplx-extra c) 'fprint))
+                    (indent (flatten (map field-print-c (cmplx-fields c))))
+                    (indent (filter-extra (cmplx-extra c) 'print))
                     (~a "}")))))
    (define (c-type c)
      (cmplx-name c))])
@@ -912,10 +915,10 @@
          (mkfields {Tag tableTag} {uint32 checksum unused hex} {Offset32 offset} {uint32 length})
          #:extra (list (cons 'field
                              (list (~a "void *parsed;")
-                                   (~a "void (*fprint)(int f, int indent, void *parsed);")))
-                       (cons 'fprint
-                             (list (~a "if(v->fprint != nil && v->parsed != nil)")
-                                   (~a "\tv->fprint(f, indent+indentΔ, v->parsed);")))))
+                                   (~a "void (*print)(Biobuf *f, int indent, void *parsed);")))
+                       (cons 'print
+                             (list (~a "if(v->print != nil && v->parsed != nil)")
+                                   (~a "\tv->print(f, indent+indentΔ, v->parsed);")))))
 
 (define (c-friendly-name t)
   (string-replace (string-trim (string-downcase t)) "/" "∕"))
@@ -936,7 +939,7 @@
           (~a "\t\t\tgoto err;")
           (~a "\t\t}")
           (~a "\t\trec->parsed = v->" (ptr c) ";")
-          (~a "\t\trec->fprint = (void*)fprint_" (cmplx-name c) ";")
+          (~a "\t\trec->print = (void*)print_" (cmplx-name c) ";")
           (~a "\t\tbreak;")))
   (list (cons 'field (map (λ (c) (~a (cmplx-name c) " *" (ptr c) ";")) tagged))
         (cons 'read
@@ -949,7 +952,8 @@
                     (~a "\tswitch(rec->tableTag){")
                     (map case-statement tagged)
                     (~a "\t}")
-                    (~a "\tctxpoprange(ctx);")
+                    (~a "\tif(ctxpoprange(ctx) < 0)")
+                    (~a "\t\tgoto err;")
                     (~a "}")))))
 
 (mkcmplx TableDirectory
--- a/test.c
+++ b/test.c
@@ -3,39 +3,112 @@
 #include <bio.h>
 
 typedef struct Ctx Ctx;
+typedef struct Range Range;
 
 struct Ctx {
-	u8int buf[8192];
 	Biobuf *f;
+	Range *r;
+	u8int *buf;
+	int bufsz;
+	int off;
 };
 
+struct Range {
+	int start;
+	int len;
+	int prevoff;
+	Range *par;
+};
+
 int
-ctxpushrange(Ctx *ctx, int offset, int len)
+ctxpushrange(Ctx *ctx, int off, int len)
 {
-	int r;
-	USED(len);
-	if((r = Bseek(ctx->f, offset, 0)) != offset){
-		werrstr("seek offset: need %d, got %d", offset, r);
-		return -1;
+	Range *r;
+	int x;
+
+	r = nil;
+	if(ctx->r != nil){
+		if(off+len > ctx->r->len){
+			werrstr("range overflow by %d bytes", off+len - ctx->r->len);
+			goto err;
+		}
+		off += ctx->r->start;
 	}
+	if((r = malloc(sizeof(*r))) == nil){
+		werrstr("no memory");
+		goto err;
+	}
+	r->par = ctx->r;
+	r->start = off;
+	r->len = len;
+	r->prevoff = ctx->off;
+	if((x = Bseek(ctx->f, off, 0)) != off){
+		werrstr("seek offset: need %d, got %d", off, x);
+		goto err;
+	}
+	ctx->off = off;
+	ctx->r = r;
 	return 0;
+err:
+	free(r);
+	werrstr("ctxpushrange: %r");
+	return -1;
 }
 
-void
+int
 ctxpoprange(Ctx *ctx)
 {
-	Bseek(ctx->f, 0, 0);
+	Range *r;
+	int x;
+
+	r = ctx->r;
+	if(r == nil){
+		werrstr("pop without push");
+		goto err;
+	}
+	if((x = Bseek(ctx->f, r->prevoff, 0)) != r->prevoff){
+		werrstr("seek offset: need %d, got %d", r->prevoff, x);
+		goto err;
+	}
+	ctx->off = r->prevoff;
+	ctx->r = r->par;
+	free(r);
+	return 0;
+err:
+	werrstr("ctxpoprange: %r");
+	return -1;
 }
 
 u8int *
 ctxreadn(Ctx *ctx, int n)
 {
-	int r;
-	if((r = Bread(ctx->f, ctx->buf, n)) != n){
-		werrstr("short read: need %d, got %d", n, r);
-		return nil;
+	Range *r;
+	u8int *b;
+	int x;
+
+	r = ctx->r;
+	if(r != nil && ctx->off+n > r->start+r->len){
+		werrstr("short read: need %d at %d, have %d at %d", n, ctx->off, r->len, r->start);
+		goto err;
 	}
+	if(n > ctx->bufsz){
+		if((b = realloc(ctx->buf, n)) == nil){
+			werrstr("no memory");
+			goto err;
+		}
+		ctx->buf = b;
+		ctx->bufsz = n;
+	}
+	if((x = Bread(ctx->f, ctx->buf, n)) != n){
+		werrstr("short read: need %d, got %d; off %d", n, x, ctx->off);
+		goto err;
+	}
+	ctx->off += n;
+
 	return ctx->buf;
+err:
+	werrstr("ctxreadn: %r");
+	return nil;
 }
 
 int
@@ -45,17 +118,21 @@
 	int (*fun)(Ctx*, void*);
 	u8int *arr;
 
-	if((arr = calloc(num, elsz)) == nil)
-		return -1;
+	if((arr = calloc(num, elsz)) == nil){
+		werrstr("no memory");
+		goto err;
+	}
 	fun = fun_;
 	for(i = 0; i < num; i++){
-		if(fun(ctx, arr + i*elsz) < 0){
-			free(arr);
-			return -1;
-		}
+		if(fun(ctx, arr + i*elsz) < 0)
+			goto err;
 	}
 	*arr_ = arr;
 	return 0;
+err:
+	free(arr);
+	werrstr("ctxarray: %r");
+	return -1;
 }
 
 #include "out.h"
@@ -64,22 +141,25 @@
 main(int argc, char **argv)
 {
 	TableDirectory td;
+	Biobuf *out;
 	Ctx ctx;
 	int i;
 
 	otfinit();
+	out = Bfdopen(1, OWRITE);
 	for(i = 1; i < argc; i++){
-		print("%s\n", argv[i]);
+		Bprint(out, "%s\n", argv[i]);
 		if((ctx.f = Bopen(argv[i], OREAD)) == nil){
 			fprint(2, "%r\n");
 		}else if(read_TableDirectory(&ctx, &td) != 0){
 			fprint(2, "%s: %r\n", argv[i]);
 		} else {
-			fprint_TableDirectory(1, 0, &td);
+			print_TableDirectory(out, 0, &td);
 		}
 		if(ctx.f != nil)
 			Bterm(ctx.f);
 	}
+	Bterm(out);
 
 	exits(nil);
 }