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;