shithub: pdffs

Download patch

ref: ecd40a88198f1a03b0e87a4f3066f944f09cf0d8
parent: 745debcdfb49837a82d112c2623b7a763fdf2cd0
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sun Aug 30 13:39:14 EDT 2020

move stuff around and just use Biobuf* everywhere

--- a/buffer.c
+++ b/buffer.c
@@ -58,7 +58,7 @@
 }
 
 int
-bufreadn(Buffer *b, void *bio, int sz)
+bufreadn(Buffer *b, Biobuf *bio, int sz)
 {
 	int n, end;
 
--- a/main.c
+++ b/main.c
@@ -17,8 +17,8 @@
 void
 threadmain(int argc, char **argv)
 {
-	int fd;
 	Pdf *pdf;
+	Biobuf *b;
 	Object *v;
 
 	quotefmtinstall();
@@ -43,9 +43,9 @@
 
 	if(argc != 1)
 		usage();
-	if((fd = open(argv[0], OREAD)) < 0)
+	if((b = Bopen(argv[0], OREAD)) == nil)
 		sysfatal("%r");
-	if((pdf = pdfopen(fd)) == nil)
+	if((pdf = pdfopen(b)) == nil)
 		sysfatal("%s: %r", argv[0]);
 	if((v = dictget(pdf->info, "Creator")) != nil)
 		fprint(2, "creator: %s\n", v->str);
--- a/misc.c
+++ b/misc.c
@@ -3,8 +3,36 @@
 #include <bio.h>
 #include "pdf.h"
 
-/* 7.2.2 whitespace */
+static char *otypes[] = {
+	[Obool] = "bool",
+	[Onum] = "num",
+	[Ostr] = "str",
+	[Oname] = "name",
+	[Oarray] = "array",
+	[Odict] = "dict",
+	[Ostream] = "stream",
+	[Onull] = "null",
+	[Oindir] = "indir",
+};
+
+Object null = {
+	.type = Onull,
+};
+
 int
+Tfmt(Fmt *f)
+{
+	Object *o;
+
+	o = va_arg(f->args, Object*);
+	if(o == nil || o == &null)
+		return fmtprint(f, "null");
+	if(o->type < 0 || o->type >= nelem(otypes))
+		return fmtprint(f, "????");
+	return fmtprint(f, "%s", otypes[o->type]);
+}
+
+int
 isws(int c)
 {
 	return /* \0 is missing on purpose */
@@ -12,7 +40,6 @@
 		c == ' ';
 }
 
-/* 7.2.2 delimeters */
 int
 isdelim(int c)
 {
--- a/object.c
+++ b/object.c
@@ -9,38 +9,9 @@
 Object *pdfarray(Pdf *pdf, Biobuf *b);
 Object *pdfdict(Pdf *pdf, Biobuf *b);
 
-Object null = {
-	.type = Onull,
-};
-
-static char *otypes[] = {
-	[Obool] = "bool",
-	[Onum] = "num",
-	[Ostr] = "str",
-	[Oname] = "name",
-	[Oarray] = "array",
-	[Odict] = "dict",
-	[Ostream] = "stream",
-	[Onull] = "null",
-	[Oindir] = "indir",
-};
-
-int
-Tfmt(Fmt *f)
-{
-	Object *o;
-
-	o = va_arg(f->args, Object*);
-	if(o == nil || o == &null)
-		return fmtprint(f, "null");
-	if(o->type < 0 || o->type >= nelem(otypes))
-		return fmtprint(f, "????");
-	return fmtprint(f, "%s", otypes[o->type]);
-}
-
 /* General function to parse an object of any type. */
 Object *
-pdfobj(Pdf *pdf, void *b)
+pdfobj(Pdf *pdf, Biobuf *b)
 {
 	Object *o, *o2;
 	vlong off;
@@ -61,6 +32,8 @@
 			if((o = pdfdict(pdf, b)) != nil){
 				/* check for attached stream */
 				off = Boffset(b);
+				do; while(isws(Bgetc(b)));
+				Bungetc(b);
 				if(Bread(b, s, 7) == 7 && memcmp(s, "stream", 6) == 0 && isws(c = s[6])){
 					/* there IS a stream */
 					if(c == '\r' && (c = Bgetc(b)) < 0)
--- a/pdf.c
+++ b/pdf.c
@@ -4,6 +4,8 @@
 #include <ctype.h>
 #include "pdf.h"
 
+int Tfmt(Fmt *f);
+
 /*
  * pre-1.5 xref section reader
  * PDF>=1.5 may have BOTH (or either) old xref format and xref streams
@@ -96,10 +98,9 @@
 }
 
 Pdf *
-pdfopen(int fd)
+pdfopen(Biobuf *b)
 {
 	Pdf *pdf;
-	Biobuf *b;
 	Object *o;
 	char tmp[64], *s, *x;
 	int xref0; /* 7.5.4 xref subsection first object number */
@@ -110,9 +111,8 @@
 
 	fmtinstall('T', Tfmt);
 
-	b = nil;
 	o = nil;
-	if((pdf = calloc(1, sizeof(*pdf))) == nil || (b = Bfdopen(fd, OREAD)) == nil)
+	if((pdf = calloc(1, sizeof(*pdf))) == nil)
 		goto err;
 	pdf->bio = b;
 
@@ -152,7 +152,7 @@
 		goto err;
 	}
 morexref:
-	off = Bseek(b, 0, 1);
+	off = Boffset(b);
 	n = sizeof(tmp)-1;
 	if((n = Bread(b, tmp, n)) < 16){
 badxref:
@@ -163,16 +163,14 @@
 	if(memcmp(tmp, "xref", 4) == 0){
 		/* 7.5.4 xref */
 		x = tmp+4;
-		nxref = -1;
-		if((xref0 = strtol(x, &x, 10)) < 0 || (nxref = strtol(x, &x, 10)) < 1){
-			werrstr("xref0=%d nxref=%d", xref0, nxref);
-			goto badxref;
-		}
-
+		xref0 = strtol(x, &x, 10);
+		nxref = strtol(x, &x, 10);
 		/* skip whitespace and move to the first subsection */
 		for(; isws(*x) && x < tmp+n; x++);
 		n = x-tmp+off;
-		if(Bseek(b, n, 0) != n || xrefread(pdf, xref0, nxref) != 0)
+		if(Bseek(b, n, 0) != n)
+			goto badxref;
+		if(xref0 >= 0 && nxref > 0 && xrefread(pdf, xref0, nxref) != 0)
 			goto badxref;
 		goto morexref; /* there could be more updates, try it */
 	}else if(memcmp(tmp, "trailer", 7) == 0){ /* 7.5.5 file trailer */
--- a/pdf.h
+++ b/pdf.h
@@ -19,6 +19,8 @@
 typedef struct Xref Xref;
 #pragma incomplete Filter
 
+#pragma varargck type "T" Object *
+
 struct Buffer {
 	uchar *b;
 	int ro;
@@ -71,7 +73,7 @@
 };
 
 struct Pdf {
-	void *bio;
+	Biobuf *bio;
 	Xref *xref;
 	int nxref; /* 7.5.4 xref subsection number of objects */
 
@@ -87,15 +89,23 @@
 
 struct Stream {
 	Buffer buf;
-	void *bio;
+	Biobuf *bio;
 };
 
 extern Object null;
 
-Pdf *pdfopen(int fd);
+Pdf *pdfopen(Biobuf *b);
 void pdfclose(Pdf *pdf);
 
-Object *pdfobj(Pdf *pdf, void *b);
+/*
+ * Parse an object.
+ */
+Object *pdfobj(Pdf *pdf, Biobuf *bio);
+
+/*
+ * Deallocate the object and all its children. Refcount is
+ * considered.
+ */
 void pdfobjfree(Object *o);
 
 /*
@@ -105,9 +115,22 @@
  */
 Object *pdfeval(Object **o);
 
+/*
+ * Increment refcount of an object. Freeing an object (or its
+ * parent) decrements ref count.
+ */
 Object *pdfref(Object *o);
 
+/*
+ * Returns 1 if the character is whitespace. 0 otherwise.
+ * See 7.2.2.
+ */
 int isws(int c);
+
+/*
+ * Returns 1 if the character is a delimiter. 0 otherwise.
+ * See 7.2.2.
+ */
 int isdelim(int c);
 
 Object *dictget(Object *o, char *name);
@@ -127,10 +150,7 @@
 void buffree(Buffer *b);
 int bufeof(Buffer *b);
 uchar *bufdata(Buffer *b, int *sz);
-int bufreadn(Buffer *b, void *bio, int sz);
+int bufreadn(Buffer *b, Biobuf *bio, int sz);
 int bufput(Buffer *b, uchar *d, int sz);
 int bufget(Buffer *b, uchar *d, int sz);
 void bufdump(Buffer *b);
-
-#pragma varargck type "T" Object *
-int Tfmt(Fmt *f);
--- a/stream.c
+++ b/stream.c
@@ -8,7 +8,7 @@
 {
 	Stream *s;
 
-	s = (void*)((char*)b - sizeof(*s));
+	s = (Stream*)((char*)b - sizeof(*s));
 
 	return bufget(&s->buf, data, n);
 }
@@ -66,7 +66,7 @@
 		buffree(&b);
 		return nil;
 	}
-	s->bio = (uchar*)(s+1);
+	s->bio = (Biobuf*)(s+1);
 	s->buf = b;
 	Binit(s->bio, Bfildes(o->pdf->bio), OREAD);
 	Biofn(s->bio, bufiof);
--- a/string.c
+++ b/string.c
@@ -62,7 +62,7 @@
 		return nil;
 
 	for(paren = sz = 0;;){
-		if((c = Bgetc(b)) <= 0)
+		if((c = Bgetc(b)) < 0)
 			break;
 
 		switch(c){
@@ -81,7 +81,7 @@
 			paren--;
 			if(paren < 1){
 				c = 0;
-				break;
+				goto end;
 			}
 			continue;
 
@@ -99,7 +99,7 @@
 				oct[i] = 0;
 				c = strtol(oct, nil, 8);
 			}else if(c >= nelem(esc) || (c = esc[c]) == 0){
-				werrstr("unknown escape char %c", c);
+				werrstr("unknown escape char '%c'", c);
 				goto err;
 			}else if(c < 0){
 				continue;
@@ -108,13 +108,13 @@
 
 		default:
 			if(paren < 1){
-				werrstr("unexpected char '%c'", c);
+				werrstr("unexpected char %02x '%c'", (u8int)c, c);
 				goto err;
 			}
 			break;
 		}
 
-		if(c <= 0)
+		if(c < 0)
 			break;
 		if(sz+1 > maxsz){
 			maxsz *= 2;
@@ -124,7 +124,7 @@
 		}
 		s[sz++] = c;
 	}
-
+end:
 	if(paren != 0){
 		werrstr("bad paren");
 		goto err;