diff options
79 files changed, 3322 insertions, 2063 deletions
diff --git a/apps/pdftool.c b/apps/pdftool.c index ce0380ee..b086eec0 100644 --- a/apps/pdftool.c +++ b/apps/pdftool.c @@ -27,10 +27,10 @@ pdf_pagetree *srcpages = nil; void die(fz_error *eo) { - fflush(stdout); - fprintf(stderr, "%s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); - fflush(stderr); - abort(); + fflush(stdout); + fz_printerror(eo); + fflush(stderr); + abort(); } void closesrc(void) @@ -70,6 +70,7 @@ void opensrc(char *filename, char *password, int loadpages) error = pdf_loadxref(src, filename); if (error) { + fz_printerror(error); fz_warn("trying to repair"); error = pdf_repairxref(src, filename); if (error) @@ -82,9 +83,9 @@ void opensrc(char *filename, char *password, int loadpages) if (src->crypt) { - error = pdf_setpassword(src->crypt, password); - if (error) - die(error); + int okay = pdf_setpassword(src->crypt, password); + if (!okay) + die(fz_throw("invalid password")); } if (loadpages) @@ -188,12 +189,11 @@ void showstream(int num, int gen) while (1) { - n = fz_read(stm, buf, sizeof buf); + error = fz_read(&n, stm, buf, sizeof buf); + if (error) + die (error); if (n == 0) break; - if (n < 0) - die(fz_ioerror(stm)); - if (showbinary) fwrite(buf, 1, n, stdout); else @@ -243,8 +243,8 @@ showmain(int argc, char **argv) case 'b': showbinary ++; break; case 'd': showdecode ++; break; default: - showusage(); - break; + showusage(); + break; } } @@ -459,7 +459,7 @@ void drawusage(void) { fprintf(stderr, - "usage: pdftool draw [options] [file.pdf pages ... ]\n" + "usage: pdftool draw [options] [file.pdf pages ... ]\n" " -b -\tdraw page in N bands\n" " -d -\tpassword for decryption\n" " -o -\tpattern (%%d for page number) for output file\n" @@ -468,7 +468,7 @@ drawusage(void) " -x \txml dump of display tree\n" " -m \tprint benchmark results\n" " example:\n" - " pdftool draw -o out%%0.3d.pnm a.pdf 1-3,5,9-\n"); + " pdftool draw -o out%%03d.pnm a.pdf 1-3,5,9-\n"); exit(1); } @@ -772,8 +772,8 @@ drawmain(int argc, char **argv) case 'x': drawmode = DRAWXML; break; case 'm': benchmark = 1; break; default: - drawusage(); - break; + drawusage(); + break; } } diff --git a/base/base_error.c b/base/base_error.c index e0bf1567..fa1c9878 100644 --- a/base/base_error.c +++ b/base/base_error.c @@ -1,74 +1,88 @@ #include "fitz-base.h" -void -fz_warn(char *fmt, ...) +fz_error * +fz_keeperror(fz_error *eo) { - va_list ap; - fprintf(stderr, "warning: "); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); + eo->refs++; + return eo; } -fz_error * -fz_throw1(char *fmt, ...) +void +fz_droperror(fz_error *eo) { - va_list ap; - fz_error *eo; + if (eo->refs > 0) + eo->refs--; + if (eo->refs == 0) + { + if (eo->cause) + fz_droperror(eo->cause); + fz_free(eo); + } +} - eo = fz_malloc(sizeof(fz_error)); - if (!eo) return fz_outofmem; +void +fz_printerror(fz_error *eo) +{ +#if 1 + if (eo->cause) + { + fz_printerror(eo->cause); + fprintf(stderr, "| %s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); + } + else + { + fprintf(stderr, "+ %s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); + } +#else + fprintf(stderr, "+ %s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); + eo = eo->cause; - eo->refs = 1; - strlcpy(eo->func, "unknown", sizeof eo->func); - strlcpy(eo->file, "unknown", sizeof eo->file); - eo->line = 0; + while (eo) + { + fprintf(stderr, "| %s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); + eo = eo->cause; + } +#endif +} - va_start(ap, fmt); - vsnprintf(eo->msg, sizeof eo->msg, fmt, ap); - eo->msg[sizeof(eo->msg) - 1] = '\0'; - va_end(ap); - return eo; +void +fz_warn(char *fmt, ...) +{ + va_list ap; + fprintf(stderr, "warning: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); } fz_error * -fz_throw0(const char *func, const char *file, int line, char *fmt, ...) +fz_throwimp(fz_error *cause, const char *func, const char *file, int line, char *fmt, ...) { - va_list ap; - fz_error *eo; + va_list ap; + fz_error *eo; - eo = fz_malloc(sizeof(fz_error)); - if (!eo) return fz_outofmem; + eo = fz_malloc(sizeof(fz_error)); + if (!eo) + return fz_outofmem; /* oops. we're *really* out of memory here. */ - eo->refs = 1; - strlcpy(eo->func, func, sizeof eo->func); - strlcpy(eo->file, file, sizeof eo->file); - eo->line = line; + eo->refs = 1; - va_start(ap, fmt); - vsnprintf(eo->msg, sizeof eo->msg, fmt, ap); - eo->msg[sizeof(eo->msg) - 1] = '\0'; - va_end(ap); + va_start(ap, fmt); + vsnprintf(eo->msg, sizeof eo->msg, fmt, ap); + eo->msg[sizeof(eo->msg) - 1] = '\0'; + va_end(ap); - if (getenv("BOMB")) - { - fflush(stdout); - fprintf(stderr, "%s:%d: %s(): %s\n", eo->file, eo->line, eo->func, eo->msg); - fflush(stderr); - abort(); - } + strlcpy(eo->func, func, sizeof eo->func); + strlcpy(eo->file, file, sizeof eo->file); + eo->line = line; - return eo; -} + if (cause) + eo->cause = fz_keeperror(cause); + else + eo->cause = nil; -void -fz_droperror(fz_error *eo) -{ - if (eo->refs > 0) - eo->refs--; - if (eo->refs == 0) - fz_free(eo); + return eo; } diff --git a/base/base_hash.c b/base/base_hash.c index dedd1c5e..b43ee611 100644 --- a/base/base_hash.c +++ b/base/base_hash.c @@ -54,7 +54,7 @@ fz_newhash(fz_hashtable **tablep, int initialsize, int keylen) table = *tablep = fz_malloc(sizeof(fz_hashtable)); if (!table) - return fz_outofmem; + return fz_throw("outofmem: hash table struct"); table->keylen = keylen; table->size = initialsize; @@ -65,12 +65,12 @@ fz_newhash(fz_hashtable **tablep, int initialsize, int keylen) { fz_free(table); *tablep = nil; - return fz_outofmem; + return fz_throw("outofmem: hash table entries (size=%d)", initialsize); } memset(table->ents, 0, sizeof(fz_hashentry) * table->size); - return nil; + return fz_okay; } void @@ -120,11 +120,11 @@ fz_resizehash(fz_hashtable *table, int newsize) oldents = table->ents; if (newsize < oldload * 8 / 10) - return fz_throw("rangecheck: resize hash too small"); + return fz_throw("assert: resize hash too small"); newents = fz_malloc(sizeof(fz_hashentry) * newsize); if (!newents) - return fz_outofmem; + return fz_throw("outofmem: hash table (size=%d)", newsize); table->size = newsize; table->load = 0; @@ -142,13 +142,14 @@ fz_resizehash(fz_hashtable *table, int newsize) table->load = oldload; table->ents = oldents; fz_free(newents); - return error; + return fz_rethrow(error, "cannot re-insert old entries"); } } } fz_free(oldents); - return nil; + + return fz_okay; } void * @@ -182,7 +183,7 @@ fz_hashinsert(fz_hashtable *table, void *key, void *val) { error = fz_resizehash(table, table->size * 2); if (error) - return error; + return fz_rethrow(error, "cannot resize hash table"); } ents = table->ents; @@ -200,12 +201,12 @@ fz_hashinsert(fz_hashtable *table, void *key, void *val) } if (memcmp(key, &ents[pos].key, table->keylen) == 0) - return fz_throw("rangecheck: overwrite hash slot"); + return fz_throw("assert: overwrite hash slot"); pos = (pos + 1) % size; } - return nil; + return fz_okay; } fz_error * @@ -219,7 +220,7 @@ fz_hashremove(fz_hashtable *table, void *key) while (1) { if (!ents[pos].val) - return fz_throw("rangecheck: remove inexistant hash entry"); + return fz_throw("assert: remove inexistant hash entry"); if (memcmp(key, &ents[pos].key, table->keylen) == 0) { @@ -244,7 +245,8 @@ fz_hashremove(fz_hashtable *table, void *key) } table->load --; - return nil; + + return fz_okay; } pos = (pos + 1) % size; diff --git a/base/base_memory.c b/base/base_memory.c index a14a3122..1fa918c2 100644 --- a/base/base_memory.c +++ b/base/base_memory.c @@ -4,30 +4,12 @@ static void *stdmalloc(fz_memorycontext *mem, int n) { -#if 0 - void *p = malloc(n); - if (!p) - fprintf(stderr, "failed to malloc %d bytes\n", n); - return p; -#else return malloc(n); -#endif } static void *stdrealloc(fz_memorycontext *mem, void *p, int n) { -#if 0 - void *np = realloc(p, n); - if (np == nil) - fprintf(stderr, "realloc failed %d nytes", n); - else if (np == p) - fprintf(stderr, "realloc kept %d\n", n); - else - fprintf(stderr, "realloc moved %d\n", n); - return np; -#else return realloc(p, n); -#endif } static void stdfree(fz_memorycontext *mem, void *p) @@ -41,9 +23,9 @@ static fz_memorycontext *curmem = &defmem; fz_error fz_koutofmem = { -1, {"out of memory"}, - {"<malloc>"}, - {"memory.c"}, - 0 + {"<internal>"}, + {"<internal>"}, + 0, 0 }; fz_memorycontext * @@ -61,15 +43,21 @@ fz_setmemorycontext(fz_memorycontext *mem) void * fz_malloc(int n) { - fz_memorycontext *mem = fz_currentmemorycontext(); - return mem->malloc(mem, n); + fz_memorycontext *mem = fz_currentmemorycontext(); + void *p = mem->malloc(mem, n); + if (!p) + fz_warn("cannot malloc %d bytes", n); + return p; } void * fz_realloc(void *p, int n) { - fz_memorycontext *mem = fz_currentmemorycontext(); - return mem->realloc(mem, p, n); + fz_memorycontext *mem = fz_currentmemorycontext(); + void *np = mem->realloc(mem, p, n); + if (np == nil) + fz_warn("cannot realloc %d bytes", n); + return np; } void diff --git a/base/base_rune.c b/base/base_rune.c index 4aa81df3..32168792 100644 --- a/base/base_rune.c +++ b/base/base_rune.c @@ -41,7 +41,8 @@ chartorune(int *rune, char *str) * 00000-0007F => T1 */ c = *(unsigned char*)str; - if(c < Tx) { + if (c < Tx) + { *rune = c; return 1; } @@ -51,13 +52,14 @@ chartorune(int *rune, char *str) * 0080-07FF => T2 Tx */ c1 = *(unsigned char*)(str+1) ^ Tx; - if(c1 & Testx) + if (c1 & Testx) goto bad; - if(c < T3) { - if(c < T2) + if (c < T3) + { + if (c < T2) goto bad; l = ((c << Bitx) | c1) & Rune2; - if(l <= Rune1) + if (l <= Rune1) goto bad; *rune = l; return 2; @@ -68,11 +70,12 @@ chartorune(int *rune, char *str) * 0800-FFFF => T3 Tx Tx */ c2 = *(unsigned char*)(str+2) ^ Tx; - if(c2 & Testx) + if (c2 & Testx) goto bad; - if(c < T4) { + if (c < T4) + { l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; - if(l <= Rune2) + if (l <= Rune2) goto bad; *rune = l; return 3; @@ -96,7 +99,8 @@ runetochar(char *str, int *rune) * 00000-0007F => 00-7F */ c = *rune; - if(c <= Rune1) { + if (c <= Rune1) + { str[0] = c; return 1; } @@ -105,7 +109,8 @@ runetochar(char *str, int *rune) * two character sequence * 0080-07FF => T2 Tx */ - if(c <= Rune2) { + if (c <= Rune2) + { str[0] = T2 | (c >> 1*Bitx); str[1] = Tx | (c & Maskx); return 2; @@ -137,12 +142,12 @@ runenlen(int *r, int nrune) int nb, c; nb = 0; - while(nrune--) { + while (nrune--) + { c = *r++; - if(c <= Rune1) + if (c <= Rune1) nb++; - else - if(c <= Rune2) + else if (c <= Rune2) nb += 2; else nb += 3; @@ -155,12 +160,13 @@ fullrune(char *str, int n) { int c; - if(n > 0) { + if (n > 0) + { c = *(unsigned char*)str; - if(c < Tx) + if (c < Tx) return 1; - if(n > 1) - if(c < T3 || n > 2) + if (n > 1) + if (c < T3 || n > 2) return 1; } return 0; diff --git a/include/fitz/base_runtime.h b/include/fitz/base_runtime.h index 717b22e9..274b2903 100644 --- a/include/fitz/base_runtime.h +++ b/include/fitz/base_runtime.h @@ -1,3 +1,17 @@ +/* + * Base Fitz runtime. + * Contains: errors, memory manager, utf-8 strings, "standard" macros + */ + +#ifndef __printflike +#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) +#else +#define __printflike(fmtarg, firstvararg) +#endif +#endif + #undef nil #define nil ((void*)0) @@ -41,23 +55,22 @@ struct fz_error_s char file[32]; char func[32]; int line; + fz_error *cause; }; #define fz_outofmem (&fz_koutofmem) extern fz_error fz_koutofmem; -#ifdef WIN32 -#define fz_throw(...) fz_throw0(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__) -#elif HAVE_C99 -#define fz_throw(...) fz_throw0(__func__, __FILE__, __LINE__, __VA_ARGS__) -#else -#define fz_throw fz_throw1 -#endif -fz_error *fz_throw0(const char *func, const char *file, int line, char *fmt, ...); -fz_error *fz_throw1(char *fmt, ...); - -void fz_warn(char *fmt, ...); +void fz_printerror(fz_error *eo); +fz_error *fz_keeperror(fz_error *eo); void fz_droperror(fz_error *eo); +void fz_warn(char *fmt, ...) __printflike(1,2); + +#define fz_throw(...) fz_throwimp(nil, __func__, __FILE__, __LINE__, __VA_ARGS__) +#define fz_rethrow(cause, ...) fz_throwimp(cause, __func__, __FILE__, __LINE__, __VA_ARGS__) +#define fz_okay ((fz_error*)0) + +fz_error *fz_throwimp(fz_error *cause, const char *func, const char *file, int line, char *fmt, ...) __printflike(5, 6); typedef struct fz_memorycontext_s fz_memorycontext; diff --git a/include/fitz/stm_filter.h b/include/fitz/stm_filter.h index f8902f98..b707838f 100644 --- a/include/fitz/stm_filter.h +++ b/include/fitz/stm_filter.h @@ -37,12 +37,12 @@ extern fz_error fz_kiodone; * Evil looking macro to create an initialize a filter struct. */ -#define FZ_NEWFILTER(TYPE,VAR,NAME) \ +#define FZ_NEWFILTER(TYPE,VAR,NAME) \ fz_error * fz_process ## NAME (fz_filter*,fz_buffer*,fz_buffer*); \ void fz_drop ## NAME (fz_filter*); \ TYPE *VAR; \ *fp = fz_malloc(sizeof(TYPE)); \ - if (!*fp) return fz_outofmem; \ + if (!*fp) return fz_throw("outofmem: %s filter struct", #NAME); \ (*fp)->refs = 1; \ (*fp)->process = fz_process ## NAME ; \ (*fp)->drop = fz_drop ## NAME ; \ diff --git a/include/fitz/stm_object.h b/include/fitz/stm_object.h index fe9c12e5..74a8e1cf 100644 --- a/include/fitz/stm_object.h +++ b/include/fitz/stm_object.h @@ -130,3 +130,5 @@ fz_error *fz_parseobj(fz_obj **objp, char *s); fz_error *fz_packobj(fz_obj **objp, char *fmt, ...); fz_error *fz_unpackobj(fz_obj *obj, char *fmt, ...); +char *fz_objkindstr(fz_obj *obj); + diff --git a/include/fitz/stm_stream.h b/include/fitz/stm_stream.h index d2ac7c94..62eb8515 100644 --- a/include/fitz/stm_stream.h +++ b/include/fitz/stm_stream.h @@ -17,7 +17,7 @@ struct fz_stream_s fz_buffer *buffer; fz_filter *filter; fz_stream *chain; - fz_error *error; + fz_error *error; /* delayed error from readbyte and peekbyte */ int file; }; @@ -31,7 +31,7 @@ fz_error *fz_openwfile(fz_stream **stmp, char *filename); fz_error *fz_openafile(fz_stream **stmp, char *filename); /* write to memory buffers! */ -fz_error * fz_openrmemory(fz_stream **stmp, unsigned char *mem, int len); +fz_error *fz_openrmemory(fz_stream **stmp, char *mem, int len); fz_error *fz_openrbuffer(fz_stream **stmp, fz_buffer *buf); fz_error *fz_openwbuffer(fz_stream **stmp, fz_buffer *buf); @@ -43,61 +43,71 @@ fz_error *fz_openwfilter(fz_stream **stmp, fz_filter *flt, fz_stream *chain); * Functions that are common to both input and output streams. */ -fz_error *fz_ioerror(fz_stream *stm); - fz_stream *fz_keepstream(fz_stream *stm); void fz_dropstream(fz_stream *stm); int fz_tell(fz_stream *stm); -int fz_seek(fz_stream *stm, int offset, int whence); +fz_error * fz_seek(fz_stream *stm, int offset, int whence); /* * Input stream functions. - * Return EOF (-1) on errors. */ int fz_rtell(fz_stream *stm); -int fz_rseek(fz_stream *stm, int offset, int whence); +fz_error * fz_rseek(fz_stream *stm, int offset, int whence); -int fz_makedata(fz_stream *stm); -int fz_read(fz_stream *stm, unsigned char *buf, int len); +fz_error * fz_readimp(fz_stream *stm); +fz_error * fz_read(int *np, fz_stream *stm, unsigned char *buf, int len); +fz_error * fz_readall(fz_buffer **bufp, fz_stream *stm); +fz_error * fz_readline(fz_stream *stm, char *buf, int max); -int fz_readall(fz_buffer **bufp, fz_stream *stm); -int fz_readline(fz_stream *stm, char *buf, int max); +/* + * Error handling when reading with readbyte/peekbyte is non-standard. + * The cause of an error is stuck into the stream struct, + * and EOF is returned. Not good, but any other way is too painful. + * So we have to be careful to check the error status eventually. + */ +fz_error *fz_readerror(fz_stream *stm); int fz_readbytex(fz_stream *stm); int fz_peekbytex(fz_stream *stm); #ifdef DEBUG + #define fz_readbyte fz_readbytex #define fz_peekbyte fz_peekbytex + #else -#define FZ_READBYTE(XXX) { \ - fz_buffer *buf = stm->buffer; \ - if (buf->rp == buf->wp) \ - if (fz_makedata(stm) < 0) \ - return EOF; \ - return buf->rp < buf->wp ? XXX : EOF ; \ +static inline int fz_readbyte(fz_stream *stm) +{ + fz_buffer *buf = stm->buffer; + if (buf->rp < buf->wp) + return *buf->rp++; + return fz_readbytex(stm); } -static inline int fz_readbyte(fz_stream *stm) FZ_READBYTE(*buf->rp++) -static inline int fz_peekbyte(fz_stream *stm) FZ_READBYTE(*buf->rp) +static inline int fz_peekbyte(fz_stream *stm) +{ + fz_buffer *buf = stm->buffer; + if (buf->rp < buf->wp) + return *buf->rp; + return fz_peekbytex(stm); +} #endif /* * Output stream functions. - * Return N or 0 on success, -1 on failure. */ int fz_wtell(fz_stream *stm); -int fz_wseek(fz_stream *stm, int offset, int whence); +fz_error * fz_wseek(fz_stream *stm, int offset, int whence); -int fz_write(fz_stream *stm, unsigned char *buf, int n); -int fz_flush(fz_stream *stm); +fz_error * fz_write(fz_stream *stm, unsigned char *buf, int n); +fz_error * fz_flush(fz_stream *stm); -int fz_printstr(fz_stream *stm, char *s); -int fz_printobj(fz_stream *stm, fz_obj *obj, int tight); -int fz_print(fz_stream *stm, char *fmt, ...); +fz_error * fz_printstr(fz_stream *stm, char *s); +fz_error * fz_printobj(fz_stream *stm, fz_obj *obj, int tight); +fz_error * fz_print(fz_stream *stm, char *fmt, ...); diff --git a/include/fitz/wld_path.h b/include/fitz/wld_path.h index 6a7c55b7..74f04fc2 100644 --- a/include/fitz/wld_path.h +++ b/include/fitz/wld_path.h @@ -76,7 +76,8 @@ fz_error *fz_closepath(fz_pathnode*); fz_error *fz_endpath(fz_pathnode*, fz_pathkind paint, fz_stroke *stroke, fz_dash *dash); fz_rect fz_boundpathnode(fz_pathnode *node, fz_matrix ctm); -void fz_debugpathnode(fz_pathnode *node); +void fz_debugpathnode(fz_pathnode *node, int indent); +void fz_printpathnode(fz_pathnode *node, int indent); fz_error *fz_newdash(fz_dash **dashp, float phase, int len, float *array); void fz_dropdash(fz_dash *dash); diff --git a/include/mupdf/syntax.h b/include/mupdf/syntax.h index d5598cd5..f9602c35 100644 --- a/include/mupdf/syntax.h +++ b/include/mupdf/syntax.h @@ -17,7 +17,7 @@ enum }; /* lex.c */ -int pdf_lex(fz_stream *f, unsigned char *buf, int n, int *len); +fz_error *pdf_lex(int *token, fz_stream *f, unsigned char *buf, int n, int *len); /* parse.c */ fz_error *pdf_parsearray(fz_obj **op, fz_stream *f, char *buf, int cap); @@ -54,9 +54,11 @@ struct pdf_crypt_s /* crypt.c */ fz_error *pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); fz_error *pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj *id); -fz_error *pdf_setpassword(pdf_crypt *crypt, char *pw); -fz_error *pdf_setuserpassword(pdf_crypt *crypt, char *pw, int pwlen); -fz_error *pdf_setownerpassword(pdf_crypt *crypt, char *pw, int pwlen); + +int pdf_setpassword(pdf_crypt *crypt, char *pw); +int pdf_setuserpassword(pdf_crypt *crypt, char *pw, int pwlen); +int pdf_setownerpassword(pdf_crypt *crypt, char *pw, int pwlen); + fz_error *pdf_cryptstream(fz_filter **fp, pdf_crypt *crypt, int oid, int gid); void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid); void pdf_dropcrypt(pdf_crypt *crypt); diff --git a/include/mupdf/xref.h b/include/mupdf/xref.h index 3143719d..23b7e135 100644 --- a/include/mupdf/xref.h +++ b/include/mupdf/xref.h @@ -8,7 +8,7 @@ typedef struct pdf_xref_s pdf_xref; struct pdf_xref_s { fz_stream *file; - float version; + int version; int startxref; pdf_crypt *crypt; diff --git a/mupdf/pdf_annot.c b/mupdf/pdf_annot.c index da4dbe80..a2839f6e 100644 --- a/mupdf/pdf_annot.c +++ b/mupdf/pdf_annot.c @@ -90,8 +90,8 @@ pdf_loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) { bbox = pdf_torect(obj); pdf_logpage("rect [%g %g %g %g]\n", - bbox.x0, bbox.y0, - bbox.x1, bbox.y1); + bbox.x0, bbox.y0, + bbox.x1, bbox.y1); } else bbox = fz_emptyrect; diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index 2e58246c..55e33fa1 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" void pdf_initgstate(pdf_gstate *gs) @@ -49,7 +49,7 @@ pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) error = pdf_flushtext(csi); if (error) - return error; + return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; @@ -73,7 +73,7 @@ pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) if (!strcmp(cs->name, "Lab")) mat->kind = PDF_MLAB; - return nil; + return fz_okay; } fz_error * @@ -87,7 +87,7 @@ pdf_setcolor(pdf_csi *csi, int what, float *v) error = pdf_flushtext(csi); if (error) - return error; + return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; @@ -121,10 +121,10 @@ Lindexed: break; default: - return fz_throw("syntaxerror: color not compatible with material"); + return fz_throw("color incompatible with material"); } - return nil; + return fz_okay; } fz_error * @@ -136,7 +136,7 @@ pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) error = pdf_flushtext(csi); if (error) - return error; + return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; @@ -150,9 +150,13 @@ pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) mat->pattern = nil; if (v) - return pdf_setcolor(csi, what, v); + { + error = pdf_setcolor(csi, what, v); + if (error) + return fz_rethrow(error, "cannot set color"); + } - return nil; + return fz_okay; } fz_error * @@ -164,7 +168,7 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade) error = pdf_flushtext(csi); if (error) - return error; + return fz_rethrow(error, "cannot finish text node (state change)"); mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; @@ -174,7 +178,7 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade) mat->kind = PDF_MSHADE; mat->shade = fz_keepshade(shade); - return nil; + return fz_okay; } fz_error * @@ -193,44 +197,54 @@ pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path) { error = fz_newdash(&dash, gs->dashphase, gs->dashlen, gs->dashlist); if (error) - return error; + return fz_rethrow(error, "cannot create dash pattern"); } else dash = nil; error = fz_endpath(path, FZ_STROKE, &stroke, dash); - if (error) { + if (error) + { fz_dropdash(dash); - return error; + return fz_rethrow(error, "cannot finish path node"); } - return nil; + return fz_okay; } fz_error * pdf_buildfillpath(pdf_gstate *gs, fz_pathnode *path, int eofill) { - return fz_endpath(path, eofill ? FZ_EOFILL : FZ_FILL, nil, nil); + fz_error *error; + error = fz_endpath(path, eofill ? FZ_EOFILL : FZ_FILL, nil, nil); + if (error) + return fz_rethrow(error, "cannot finish path node"); + return fz_okay; } static fz_error * -addcolorshape(pdf_gstate *gs, fz_node *shape, float alpha, fz_colorspace *cs, float *v) +addcolorshape(pdf_gstate *gs, fz_node *shape, fz_colorspace *cs, float *v) { fz_error *error; fz_node *mask; fz_node *solid; error = fz_newmasknode(&mask); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create mask node"); - error = fz_newsolidnode(&solid, alpha, cs, cs->n, v); - if (error) return error; + error = fz_newsolidnode(&solid, 1.0, cs, cs->n, v); + if (error) + { + fz_dropnode(mask); + return fz_rethrow(error, "cannot create color node"); + } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, solid); fz_insertnodelast(gs->head, mask); - return nil; + return fz_okay; } static fz_error * @@ -241,18 +255,29 @@ addinvisibleshape(pdf_gstate *gs, fz_node *shape) fz_pathnode *path; error = fz_newmasknode(&mask); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create mask node"); error = fz_newpathnode(&path); - if (error) return error; + if (error) + { + fz_dropnode(mask); + return fz_rethrow(error, "cannot create path node"); + } + error = fz_endpath(path, FZ_FILL, nil, nil); - if (error) return error; + if (error) + { + fz_dropnode(mask); + fz_dropnode((fz_node*)path); + return fz_rethrow(error, "cannot finish path node"); + } fz_insertnodelast(mask, (fz_node*)path); fz_insertnodelast(mask, shape); fz_insertnodelast(gs->head, mask); - return nil; + return fz_okay; } static fz_matrix getmatrix(fz_node *node) @@ -271,19 +296,17 @@ static fz_matrix getmatrix(fz_node *node) static fz_error * addpatternshape(pdf_gstate *gs, fz_node *shape, - pdf_pattern *pat, fz_colorspace *cs, float *v) + pdf_pattern *pat, fz_colorspace *cs, float *v) { fz_error *error; fz_node *xform; fz_node *over; fz_node *mask; - fz_node *meta; fz_node *link; fz_matrix ctm; fz_matrix inv; fz_matrix ptm; fz_rect bbox; - fz_obj *dict; int x, y, x0, y0, x1, y1; /* patterns are painted in user space */ @@ -291,30 +314,32 @@ addpatternshape(pdf_gstate *gs, fz_node *shape, inv = fz_invertmatrix(ctm); error = fz_newmasknode(&mask); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create mask node"); ptm = fz_concat(pat->matrix, fz_invertmatrix(ctm)); error = fz_newtransformnode(&xform, ptm); - if (error) return error; - - error = fz_packobj(&dict, "<< /Tree %p /XStep %f /YStep %f " - " /Matrix[%f %f %f %f %f %f] >>", - pat->tree, pat->xstep, pat->ystep, - pat->matrix.a, pat->matrix.b, - pat->matrix.c, pat->matrix.d, - pat->matrix.e, pat->matrix.f); - if (error) return error; - - error = fz_newmetanode(&meta, "Pattern", dict); - if (error) return error; + if (error) + { + fz_dropnode(mask); + return fz_rethrow(error, "cannot create transform node"); + } error = fz_newovernode(&over); - if (error) return error; + if (error) + { + fz_dropnode(xform); + fz_dropnode(mask); + return fz_rethrow(error, "cannot create over node"); + } fz_insertnodelast(mask, shape); - fz_insertnodelast(mask, meta); - fz_insertnodelast(meta, xform); + fz_insertnodelast(mask, xform); fz_insertnodelast(xform, over); + xform = nil; + mask = nil; + + /* over, xform, mask are now owned by the tree */ /* get bbox of shape in pattern space for stamping */ ptm = fz_concat(ctm, fz_invertmatrix(pat->matrix)); @@ -337,19 +362,29 @@ addpatternshape(pdf_gstate *gs, fz_node *shape, { ptm = fz_translate(x * pat->xstep, y * pat->ystep); error = fz_newtransformnode(&xform, ptm); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create transform node for stamp"); error = fz_newlinknode(&link, pat->tree); - if (error) return error; + if (error) + { + fz_dropnode(xform); + return fz_rethrow(error, "cannot create link node for stamp"); + } fz_insertnodelast(xform, link); fz_insertnodelast(over, xform); } } if (pat->ismask) - return addcolorshape(gs, mask, 1.0, cs, v); + { + error = addcolorshape(gs, mask, cs, v); + if (error) + return fz_rethrow(error, "cannot add colored shape"); + return fz_okay; + } fz_insertnodelast(gs->head, mask); - return nil; + return fz_okay; } fz_error * @@ -359,11 +394,12 @@ pdf_addshade(pdf_gstate *gs, fz_shade *shade) fz_node *node; error = fz_newshadenode(&node, shade); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create shade node"); fz_insertnodelast(gs->head, node); - return nil; + return fz_okay; } static fz_error * @@ -382,21 +418,44 @@ addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade) inv = fz_invertmatrix(ctm); error = fz_newtransformnode(&xform, inv); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create transform node"); error = fz_newmasknode(&mask); - if (error) return error; + if (error) + { + fz_dropnode(xform); + return fz_rethrow(error, "cannot create mask node"); + } error = fz_newshadenode(&color, shade); - if (error) return error; + if (error) + { + fz_dropnode(mask); + fz_dropnode(xform); + return fz_rethrow(error, "cannot create shade node"); + } if (shade->usebackground) { error = fz_newovernode(&over); - if (error) return error; + if (error) + { + fz_dropnode(color); + fz_dropnode(mask); + fz_dropnode(xform); + return fz_rethrow(error, "cannot create over node for background color"); + } error = fz_newsolidnode(&bgnd, 1.0, shade->cs, shade->cs->n, shade->background); - if (error) return error; + if (error) + { + fz_dropnode(over); + fz_dropnode(color); + fz_dropnode(mask); + fz_dropnode(xform); + return fz_rethrow(error, "cannot create solid node for background color");; + } fz_insertnodelast(mask, shape); fz_insertnodelast(over, bgnd); @@ -413,49 +472,83 @@ addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade) fz_insertnodelast(gs->head, mask); } - return nil; + return fz_okay; } fz_error * pdf_addfillshape(pdf_gstate *gs, fz_node *shape) { + fz_error *error; + switch (gs->fill.kind) { case PDF_MNONE: fz_insertnodelast(gs->head, shape); - return nil; + break; + case PDF_MCOLOR: case PDF_MLAB: case PDF_MINDEXED: - return addcolorshape(gs, shape, gs->fill.alpha, gs->fill.cs, gs->fill.v); + error = addcolorshape(gs, shape, gs->fill.cs, gs->fill.v); + if (error) + return fz_rethrow(error, "cannot add colored shape"); + break; + case PDF_MPATTERN: - return addpatternshape(gs, shape, gs->fill.pattern, gs->fill.cs, gs->fill.v); + error = addpatternshape(gs, shape, gs->fill.pattern, gs->fill.cs, gs->fill.v); + if (error) + return fz_rethrow(error, "cannot add pattern shape"); + break; + case PDF_MSHADE: - return addshadeshape(gs, shape, gs->fill.shade); + error = addshadeshape(gs, shape, gs->fill.shade); + if (error) + return fz_rethrow(error, "cannot add shade shape"); + break; + default: - return fz_throw("unimplemented material"); + return fz_throw("assert: unknown material"); } + + return fz_okay; } fz_error * pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape) { + fz_error *error; + switch (gs->stroke.kind) { case PDF_MNONE: fz_insertnodelast(gs->head, shape); - return nil; + break; + case PDF_MCOLOR: case PDF_MLAB: case PDF_MINDEXED: - return addcolorshape(gs, shape, gs->stroke.alpha, gs->stroke.cs, gs->stroke.v); + error = addcolorshape(gs, shape, gs->stroke.cs, gs->stroke.v); + if (error) + return fz_rethrow(error, "cannot add colored shape"); + break; + case PDF_MPATTERN: - return addpatternshape(gs, shape, gs->stroke.pattern, gs->stroke.cs, gs->stroke.v); + error = addpatternshape(gs, shape, gs->stroke.pattern, gs->stroke.cs, gs->stroke.v); + if (error) + return fz_rethrow(error, "cannot add pattern shape"); + break; + case PDF_MSHADE: - return addshadeshape(gs, shape, gs->stroke.shade); + error = addshadeshape(gs, shape, gs->stroke.shade); + if (error) + return fz_rethrow(error, "cannot add shade shape"); + break; + default: - return fz_throw("unimplemented material"); + return fz_throw("assert: unknown material"); } + + return fz_okay; } fz_error * @@ -466,17 +559,22 @@ pdf_addclipmask(pdf_gstate *gs, fz_node *shape) fz_node *over; error = fz_newmasknode(&mask); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create mask node"); error = fz_newovernode(&over); - if (error) return error; + if (error) + { + fz_dropnode(mask); + return fz_rethrow(error, "cannot create over node"); + } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, over); fz_insertnodelast(gs->head, mask); gs->head = over; - return nil; + return fz_okay; } fz_error * @@ -486,13 +584,14 @@ pdf_addtransform(pdf_gstate *gs, fz_node *transform) fz_node *over; error = fz_newovernode(&over); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create over node"); fz_insertnodelast(gs->head, transform); fz_insertnodelast(transform, over); gs->head = over; - return nil; + return fz_okay; } fz_error * @@ -505,24 +604,35 @@ pdf_showimage(pdf_csi *csi, pdf_image *img) error = fz_newimagenode(&color, (fz_image*)img); if (error) - return error; + return fz_rethrow(error, "cannot create image node"); if (img->super.n == 0 && img->super.a == 1) { error = pdf_addfillshape(csi->gstate + csi->gtop, color); - if (error) { + if (error) + { fz_dropnode(color); - return error; + return fz_rethrow(error, "cannot add filled image mask"); } } + else { if (img->mask) { error = fz_newimagenode(&shape, (fz_image*)img->mask); - if (error) return error; + if (error) + { + fz_dropnode(color); + return fz_rethrow(error, "cannot create image node for image mask"); + } error = fz_newmasknode(&mask); - if (error) return error; + if (error) + { + fz_dropnode(shape); + fz_dropnode(color); + return fz_rethrow(error, "cannot create mask node for image mask"); + } fz_insertnodelast(mask, shape); fz_insertnodelast(mask, color); fz_insertnodelast(csi->gstate[csi->gtop].head, mask); @@ -533,76 +643,141 @@ pdf_showimage(pdf_csi *csi, pdf_image *img) } } - return nil; + return fz_okay; } fz_error * pdf_showpath(pdf_csi *csi, - int doclose, int dofill, int dostroke, int evenodd) + int doclose, int dofill, int dostroke, int evenodd) { pdf_gstate *gstate = csi->gstate + csi->gtop; fz_error *error; fz_pathnode *spath; fz_pathnode *fpath; + fz_pathnode *clip; + + /* TODO this is too messy and hairy with memory cleanups */ if (doclose) { error = fz_closepath(csi->path); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create path node"); + } + + /* + * Prepare the various copies of the path node. + */ + + if (csi->clip) + { + error = fz_clonepathnode(&clip, csi->path); + if (error) + return error; } if (dofill && dostroke) { fpath = csi->path; error = fz_clonepathnode(&spath, fpath); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot duplicate path node"); + } + else if (dofill) + { + fpath = csi->path; + spath = nil; + } + else if (dostroke) + { + fpath = nil; + spath = csi->path; } else { - spath = fpath = csi->path; + fz_dropnode((fz_node*)csi->path); + spath = nil; + fpath = nil; } + csi->path = nil; + + /* + * Add nodes to the tree. + */ + if (dofill) { error = pdf_buildfillpath(gstate, fpath, evenodd); - if (error) return error; + if (error) + { + if (fpath) fz_dropnode((fz_node*)fpath); + if (spath) fz_dropnode((fz_node*)spath); + if (clip) fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot finish fill path"); + } + error = pdf_addfillshape(gstate, (fz_node*)fpath); - if (error) return error; + if (error) + { + if (fpath) fz_dropnode((fz_node*)fpath); + if (spath) fz_dropnode((fz_node*)spath); + if (clip) fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot add filled path"); + } } if (dostroke) { error = pdf_buildstrokepath(gstate, spath); - if (error) return error; + if (error) + { + if (fpath) fz_dropnode((fz_node*)fpath); + if (spath) fz_dropnode((fz_node*)spath); + if (clip) fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot finish stroke path"); + } + error = pdf_addstrokeshape(gstate, (fz_node*)spath); - if (error) return error; + if (error) + { + if (fpath) fz_dropnode((fz_node*)fpath); + if (spath) fz_dropnode((fz_node*)spath); + if (clip) fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot add stroked path"); + } } if (csi->clip) { - fz_pathnode *clip; - error = fz_clonepathnode(&clip, csi->path); - if (error) return error; error = fz_endpath(clip, FZ_FILL, nil, nil); - if (error) return error; + if (error) + { + fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot finish clip path"); + } + error = pdf_addclipmask(gstate, (fz_node*)clip); - if (error) return error; - csi->clip = 0; - } + if (error) + { + fz_dropnode((fz_node*)clip); + return fz_rethrow(error, "cannot add clip mask"); + } - if (!dofill && !dostroke) - { - fz_dropnode((fz_node*)csi->path); + csi->clip = 0; } - csi->path = nil; - error = fz_newpathnode(&csi->path); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create path node");; - return nil; + return fz_okay; } +/* + * Text + */ + fz_error * pdf_flushtext(pdf_csi *csi) { @@ -618,13 +793,13 @@ pdf_flushtext(pdf_csi *csi) case 2: /* stroke + fill */ error = pdf_addfillshape(gstate, (fz_node*)csi->text); if (error) - return error; + return fz_rethrow(error, "cannot add filled text"); break; case 3: /* invisible */ error = addinvisibleshape(gstate, (fz_node*)csi->text); if (error) - return error; + return fz_rethrow(error, "cannot add invisible text"); break; case 4: /* fill + clip */ @@ -632,21 +807,28 @@ pdf_flushtext(pdf_csi *csi) case 6: /* stroke + fill + clip */ { fz_textnode *temp; + error = fz_clonetextnode(&temp, csi->text); if (error) - return error; + return fz_rethrow(error, "cannot duplicate text"); + error = pdf_addfillshape(gstate, (fz_node*)temp); if (error) - return error; + { + fz_dropnode((fz_node*)temp); + return fz_rethrow(error, "cannot add filled text"); + } + + /* FIXME stroked text */ } /* fall through */ - case 7: /* invisible clip */ + case 7: /* invisible clip ( + fallthrough clips ) */ if (!csi->textclip) { error = fz_newovernode(&csi->textclip); if (error) - return error; + return fz_rethrow(error, "cannot create over node"); } fz_insertnodelast(csi->textclip, (fz_node*)csi->text); break; @@ -655,7 +837,7 @@ pdf_flushtext(pdf_csi *csi) csi->text = nil; } - return nil; + return fz_okay; } fz_error * @@ -687,18 +869,20 @@ showglyph(pdf_csi *csi, int cid) /* flush buffered text if face or matrix or rendermode has changed */ if (!csi->text || - ((fz_font*)font) != csi->text->font || - fabs(trm.a - csi->text->trm.a) > FLT_EPSILON || - fabs(trm.b - csi->text->trm.b) > FLT_EPSILON || - fabs(trm.c - csi->text->trm.c) > FLT_EPSILON || - fabs(trm.d - csi->text->trm.d) > FLT_EPSILON || - gstate->render != csi->textmode) + ((fz_font*)font) != csi->text->font || + fabs(trm.a - csi->text->trm.a) > FLT_EPSILON || + fabs(trm.b - csi->text->trm.b) > FLT_EPSILON || + fabs(trm.c - csi->text->trm.c) > FLT_EPSILON || + fabs(trm.d - csi->text->trm.d) > FLT_EPSILON || + gstate->render != csi->textmode) { error = pdf_flushtext(csi); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot finish text node (face/matrix change)"); error = fz_newtextnode(&csi->text, (fz_font*)font); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create text node"); csi->text->trm = trm; csi->text->trm.e = 0; @@ -709,7 +893,7 @@ showglyph(pdf_csi *csi, int cid) /* add glyph to textobject */ error = fz_addtext(csi->text, cid, trm.e, trm.f); if (error) - return error; + return fz_rethrow(error, "cannot add glyph to text node"); if (font->super.wmode == 0) { @@ -725,7 +909,7 @@ showglyph(pdf_csi *csi, int cid) csi->tm = fz_concat(fz_translate(0, ty), csi->tm); } - return nil; + return fz_okay; } void @@ -758,7 +942,8 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) if (fz_isstring(item)) { error = pdf_showtext(csi, item); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot draw text item"); } else { @@ -768,7 +953,7 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) return nil; } - buf = (unsigned char *) fz_tostrbuf(text); + buf = fz_tostrbuf(text); len = fz_tostrlen(text); end = buf + len; @@ -781,12 +966,12 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) error = showglyph(csi, cid); if (error) - return error; + return fz_rethrow(error, "cannot draw glyph"); if (cpt == 32) showspace(csi, gstate->wordspace); } - return nil; + return fz_okay; } diff --git a/mupdf/pdf_cmap.c b/mupdf/pdf_cmap.c index 997e5afb..9031aeb6 100644 --- a/mupdf/pdf_cmap.c +++ b/mupdf/pdf_cmap.c @@ -72,7 +72,7 @@ pdf_newcmap(pdf_cmap **cmapp) cmap = *cmapp = fz_malloc(sizeof(pdf_cmap)); if (!cmap) - return fz_outofmem; + return fz_throw("outofmem: cmap struct"); cmap->refs = 1; strcpy(cmap->cmapname, ""); @@ -92,7 +92,7 @@ pdf_newcmap(pdf_cmap **cmapp) cmap->tcap = 0; cmap->table = nil; - return nil; + return fz_okay; } pdf_cmap * @@ -214,7 +214,7 @@ pdf_addcodespace(pdf_cmap *cmap, unsigned lo, unsigned hi, int n) int i; if (cmap->ncspace + 1 == MAXCODESPACE) - return fz_throw("rangelimit: too many code space ranges"); + return fz_throw("assert: too many code space ranges"); cmap->cspace[cmap->ncspace].n = n; @@ -227,7 +227,7 @@ pdf_addcodespace(pdf_cmap *cmap, unsigned lo, unsigned hi, int n) cmap->ncspace ++; - return nil; + return fz_okay; } /* @@ -241,14 +241,14 @@ addtable(pdf_cmap *cmap, int value) int newcap = cmap->tcap == 0 ? 256 : cmap->tcap * 2; int *newtable = fz_realloc(cmap->table, newcap * sizeof(int)); if (!newtable) - return fz_outofmem; + return fz_throw("outofmem: cmap table"); cmap->tcap = newcap; cmap->table = newtable; } cmap->table[cmap->tlen++] = value; - return nil; + return fz_okay; } /* @@ -263,7 +263,7 @@ addrange(pdf_cmap *cmap, int low, int high, int flag, int offset) int newcap = cmap->rcap == 0 ? 256 : cmap->rcap * 2; newranges = fz_realloc(cmap->ranges, newcap * sizeof(pdf_range)); if (!newranges) - return fz_outofmem; + return fz_throw("outofmem: cmap ranges"); cmap->rcap = newcap; cmap->ranges = newranges; } @@ -274,7 +274,7 @@ addrange(pdf_cmap *cmap, int low, int high, int flag, int offset) cmap->ranges[cmap->rlen].offset = offset; cmap->rlen ++; - return nil; + return fz_okay; } /* @@ -295,10 +295,14 @@ pdf_maprangetotable(pdf_cmap *cmap, int low, int *table, int len) { error = addtable(cmap, table[i]); if (error) - return error; + return fz_rethrow(error, "cannot add range-to-table index"); } - return addrange(cmap, low, high, TABLE, offset); + error = addrange(cmap, low, high, TABLE, offset); + if (error) + return fz_rethrow(error, "cannot add range-to-table range"); + + return fz_okay; } /* @@ -307,7 +311,11 @@ pdf_maprangetotable(pdf_cmap *cmap, int low, int *table, int len) fz_error * pdf_maprangetorange(pdf_cmap *cmap, int low, int high, int offset) { - return addrange(cmap, low, high, high - low == 0 ? SINGLE : RANGE, offset); + fz_error *error; + error = addrange(cmap, low, high, high - low == 0 ? SINGLE : RANGE, offset); + if (error) + return fz_rethrow(error, "cannot add range-to-range mapping"); + return fz_okay; } /* @@ -321,22 +329,31 @@ pdf_maponetomany(pdf_cmap *cmap, int low, int *values, int len) int i; if (len == 1) - return addrange(cmap, low, low, SINGLE, values[0]); + { + error = addrange(cmap, low, low, SINGLE, values[0]); + if (error) + return fz_rethrow(error, "cannot add one-to-one mapping"); + return fz_okay; + } offset = cmap->tlen; error = addtable(cmap, len); if (error) - return error; + return fz_rethrow(error, "cannot add one-to-many table length"); for (i = 0; i < len; i++) { addtable(cmap, values[i]); if (error) - return error; + return fz_rethrow(error, "cannot add one-to-many table index"); } - return addrange(cmap, low, low, MULTI, offset); + error = addrange(cmap, low, low, MULTI, offset); + if (error) + return fz_rethrow(error, "cannot add one-to-many mapping"); + + return fz_okay; } /* @@ -385,7 +402,7 @@ pdf_sortcmap(pdf_cmap *cmap) a->high = b->high; error = addtable(cmap, b->offset); if (error) - return error; + return fz_rethrow(error, "cannot convert LS -> L"); } /* LR -> LR */ @@ -412,11 +429,11 @@ pdf_sortcmap(pdf_cmap *cmap) error = addtable(cmap, a->offset); if (error) - return error; + return fz_rethrow(error, "cannot convert SS -> L"); error = addtable(cmap, b->offset); if (error) - return error; + return fz_rethrow(error, "cannot convert SS -> L"); a->offset = cmap->tlen - 2; } @@ -427,7 +444,7 @@ pdf_sortcmap(pdf_cmap *cmap) a->high = b->high; error = addtable(cmap, b->offset); if (error) - return error; + return fz_rethrow(error, "cannot convert LS -> L"); } /* XX -> XX */ @@ -453,7 +470,7 @@ pdf_sortcmap(pdf_cmap *cmap) newranges = fz_realloc(cmap->ranges, cmap->rlen * sizeof(pdf_range)); if (!newranges) - return fz_outofmem; + return fz_throw("outofmem: cmap ranges"); cmap->rcap = cmap->rlen; cmap->ranges = newranges; @@ -461,12 +478,12 @@ pdf_sortcmap(pdf_cmap *cmap) { newtable = fz_realloc(cmap->table, cmap->tlen * sizeof(int)); if (!newtable) - return fz_outofmem; + return fz_throw("outofmem: cmap table"); cmap->tcap = cmap->tlen; cmap->table = newtable; } - return nil; + return fz_okay; } /* @@ -580,69 +597,84 @@ static int codefromstring(unsigned char *buf, int len) return a; } -static int mylex(fz_stream *file, unsigned char *buf, int n, int *sl) +static fz_error *mylex(int *token, fz_stream *file, char *buf, int n, int *sl) { - int token = pdf_lex(file, (unsigned char *) buf, n, sl); - if (token == PDF_TKEYWORD) - token = tokenfromkeyword((char *) buf); - return token; + fz_error *error; + error = pdf_lex(token, file, buf, n, sl); + if (!error && *token == PDF_TKEYWORD) + *token = tokenfromkeyword(buf); + return error; } static fz_error *parsecmapname(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - token = mylex(file, buf, sizeof buf, &len); - if (token == PDF_TNAME) { - strlcpy(cmap->cmapname, (char *) buf, sizeof(cmap->cmapname)); - return nil; + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); + + if (token == PDF_TNAME) + { + strlcpy(cmap->cmapname, buf, sizeof(cmap->cmapname)); + return fz_okay; } - return fz_throw("syntaxerror in CMap after /CMapName"); + return fz_throw("expected name"); } static fz_error *parsewmode(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - token = mylex(file, buf, sizeof buf, &len); - if (token == PDF_TINT) { - pdf_setwmode(cmap, atoi((char *) buf)); - return nil; + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); + + if (token == PDF_TINT) + { + pdf_setwmode(cmap, atoi(buf)); + return fz_okay; } - return fz_throw("syntaxerror in CMap after /WMode"); + return fz_throw("expected integer"); } static fz_error *parsecodespacerange(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int lo, hi; while (1) { - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == TENDCODESPACERANGE) - return nil; + return fz_okay; else if (token == PDF_TSTRING) { lo = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == PDF_TSTRING) { hi = codefromstring(buf, len); error = pdf_addcodespace(cmap, lo, hi, len); if (error) - return error; + return fz_rethrow(error, "cannot add code space"); } else break; } @@ -650,104 +682,110 @@ static fz_error *parsecodespacerange(pdf_cmap *cmap, fz_stream *file) else break; } - return fz_throw("syntaxerror in CMap codespacerange section"); + return fz_throw("expected string or endcodespacerange"); } static fz_error *parsecidrange(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int lo, hi, dst; while (1) { - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == TENDCIDRANGE) - return nil; + return fz_okay; else if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string or endcidrange"); lo = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string"); hi = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token != PDF_TINT) - goto cleanup; + return fz_throw("expected integer"); - dst = atoi((char *) buf); + dst = atoi(buf); error = pdf_maprangetorange(cmap, lo, hi, dst); if (error) - return error; + return fz_rethrow(error, "cannot map cidrange"); } - -cleanup: - return fz_throw("syntaxerror in CMap cidrange section"); } static fz_error *parsecidchar(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int src, dst; while (1) { - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == TENDCIDCHAR) - return nil; + return fz_okay; else if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string or endcidchar"); src = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token != PDF_TINT) - goto cleanup; + return fz_throw("expected integer"); - dst = atoi((char *) buf); + dst = atoi(buf); error = pdf_maprangetorange(cmap, src, src, dst); if (error) - return error; + return fz_rethrow(error, "cannot map cidchar"); } - -cleanup: - return fz_throw("syntaxerror in CMap cidchar section"); } static fz_error *parsebfrangearray(pdf_cmap *cmap, fz_stream *file, int lo, int hi) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int dst[256]; int i; while (1) { - token = mylex(file, buf, sizeof buf, &len); - /* Note: does not handle [ /Name /Name ... ] */ + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == PDF_TCARRAY) - return nil; + return fz_okay; + /* Note: does not handle [ /Name /Name ... ] */ else if (token != PDF_TSTRING) - return fz_throw("syntaxerror in CMap bfrange array section"); + return fz_throw("expected string or ]"); if (len / 2) { @@ -756,7 +794,7 @@ static fz_error *parsebfrangearray(pdf_cmap *cmap, fz_stream *file, int lo, int error = pdf_maponetomany(cmap, lo, dst, len / 2); if (error) - return error; + return fz_rethrow(error, "cannot map bfrange array"); } lo ++; @@ -765,31 +803,37 @@ static fz_error *parsebfrangearray(pdf_cmap *cmap, fz_stream *file, int lo, int static fz_error *parsebfrange(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int lo, hi, dst; while (1) { - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == TENDBFRANGE) - return nil; + return fz_okay; else if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string or endbfrange"); lo = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string"); hi = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == PDF_TSTRING) { @@ -798,7 +842,7 @@ static fz_error *parsebfrange(pdf_cmap *cmap, fz_stream *file) dst = codefromstring(buf, len); error = pdf_maprangetorange(cmap, lo, hi, dst); if (error) - return error; + return fz_rethrow(error, "cannot map bfrange"); } else { @@ -815,7 +859,7 @@ static fz_error *parsebfrange(pdf_cmap *cmap, fz_stream *file) dststr[i-1] ++; error = pdf_maponetomany(cmap, lo, dststr, i); if (error) - return error; + return fz_rethrow(error, "cannot map bfrange"); lo ++; } } @@ -826,45 +870,46 @@ static fz_error *parsebfrange(pdf_cmap *cmap, fz_stream *file) { error = parsebfrangearray(cmap, file, lo, hi); if (error) - return error; + return fz_rethrow(error, "cannot map bfrange"); } else { - goto cleanup; + return fz_throw("expected string or array or endbfrange"); } } - -cleanup: - return fz_throw("syntaxerror in CMap bfrange section"); } static fz_error *parsebfchar(pdf_cmap *cmap, fz_stream *file) { - unsigned char buf[256]; + fz_error *error; + char buf[256]; int token; int len; - fz_error *error; int dst[256]; int src; int i; while (1) { - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); if (token == TENDBFCHAR) - return nil; + return fz_okay; else if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string or endbfchar"); src = codefromstring(buf, len); - token = mylex(file, buf, sizeof buf, &len); + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "syntaxerror in cmap"); /* Note: does not handle /dstName */ if (token != PDF_TSTRING) - goto cleanup; + return fz_throw("expected string"); if (len / 2) { @@ -873,12 +918,9 @@ static fz_error *parsebfchar(pdf_cmap *cmap, fz_stream *file) error = pdf_maponetomany(cmap, src, dst, i); if (error) - return error; + return fz_rethrow(error, "cannot map bfchar"); } } - -cleanup: - return fz_throw("syntaxerror in CMap bfchar section"); } fz_error * @@ -887,45 +929,50 @@ pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file) fz_error *error; pdf_cmap *cmap; char key[64]; - unsigned char buf[256]; + char buf[256]; int token; int len; error = pdf_newcmap(&cmap); if (error) - return error; + return fz_rethrow(error, "cannot create cmap"); strcpy(key, ".notdef"); while (1) { - token = mylex(file, buf, sizeof buf, &len); - - if (token == PDF_TEOF) - break; - - else if (token == PDF_TERROR) + error = mylex(&token, file, buf, sizeof buf, &len); + if (error) { - error = fz_throw("syntaxerror in CMap"); + error = fz_rethrow(error, "syntaxerror in cmap"); goto cleanup; } + if (token == PDF_TEOF) + break; + else if (token == PDF_TNAME) { - if (!strcmp((char *) buf, "CMapName")) + if (!strcmp(buf, "CMapName")) { error = parsecmapname(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap after /CMapName"); goto cleanup; + } } - else if (!strcmp((char *) buf, "WMode")) + else if (!strcmp(buf, "WMode")) { error = parsewmode(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap after /WMode"); goto cleanup; + } } else - strlcpy(key, (char *) buf, sizeof key); + strlcpy(key, buf, sizeof key); } else if (token == TUSECMAP) @@ -937,35 +984,50 @@ pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file) { error = parsecodespacerange(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap codespacerange"); goto cleanup; + } } else if (token == TBEGINBFCHAR) { error = parsebfchar(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap bfchar"); goto cleanup; + } } else if (token == TBEGINCIDCHAR) { error = parsecidchar(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap cidchar"); goto cleanup; + } } else if (token == TBEGINBFRANGE) { error = parsebfrange(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap bfrange"); goto cleanup; + } } else if (token == TBEGINCIDRANGE) { error = parsecidrange(cmap, file); if (error) + { + error = fz_rethrow(error, "syntaxerror in cmap cidrange"); goto cleanup; + } } /* ignore everything else */ @@ -973,10 +1035,13 @@ pdf_parsecmap(pdf_cmap **cmapp, fz_stream *file) error = pdf_sortcmap(cmap); if (error) + { + error = fz_rethrow(error, "cannot sort cmap"); goto cleanup; + } *cmapp = cmap; - return nil; + return fz_okay; cleanup: pdf_dropcmap(cmap); @@ -989,8 +1054,8 @@ cleanup: fz_error * pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) { - fz_obj *stmobj = stmref; fz_error *error = nil; + fz_obj *stmobj = stmref; fz_stream *file; pdf_cmap *cmap = nil; pdf_cmap *usecmap; @@ -1007,15 +1072,21 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) error = pdf_resolve(&stmobj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve cmap object"); error = pdf_openstream(&file, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) + { + error = fz_rethrow(error, "cannot open cmap stream"); goto cleanup; + } error = pdf_parsecmap(&cmap, file); if (error) + { + error = fz_rethrow(error, "cannot parse cmap stream"); goto cleanup; + } fz_dropstream(file); @@ -1032,7 +1103,10 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) pdf_logfont("usecmap /%s\n", fz_toname(obj)); error = pdf_loadsystemcmap(&usecmap, fz_toname(obj)); if (error) + { + error = fz_rethrow(error, "cannot load system usecmap '%s'", fz_toname(obj)); goto cleanup; + } pdf_setusecmap(cmap, usecmap); pdf_dropcmap(usecmap); } @@ -1041,7 +1115,10 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) pdf_logfont("usecmap %d %d R\n", fz_tonum(obj), fz_togen(obj)); error = pdf_loadembeddedcmap(&usecmap, xref, obj); if (error) + { + error = fz_rethrow(error, "cannot load embedded usecmap"); goto cleanup; + } pdf_setusecmap(cmap, usecmap); pdf_dropcmap(usecmap); } @@ -1050,12 +1127,15 @@ pdf_loadembeddedcmap(pdf_cmap **cmapp, pdf_xref *xref, fz_obj *stmref) error = pdf_storeitem(xref->store, PDF_KCMAP, stmref, cmap); if (error) + { + error = fz_rethrow(error, "cannot store cmap resource"); goto cleanup; + } fz_dropobj(stmobj); *cmapp = cmap; - return nil; + return fz_okay; cleanup: if (cmap) @@ -1093,11 +1173,17 @@ pdf_loadsystemcmap(pdf_cmap **cmapp, char *name) error = fz_openrfile(&file, path); if (error) + { + error = fz_rethrow(error, "cannot open cmap file '%s'", name); goto cleanup; + } error = pdf_parsecmap(&cmap, file); if (error) + { + error = fz_rethrow(error, "cannot parse cmap file"); goto cleanup; + } fz_dropstream(file); @@ -1107,7 +1193,10 @@ pdf_loadsystemcmap(pdf_cmap **cmapp, char *name) pdf_logfont("usecmap %s\n", usecmapname); error = pdf_loadsystemcmap(&usecmap, usecmapname); if (error) + { + error = fz_rethrow(error, "cannot load system usecmap '%s'", usecmapname); goto cleanup; + } pdf_setusecmap(cmap, usecmap); pdf_dropcmap(usecmap); } @@ -1115,7 +1204,7 @@ pdf_loadsystemcmap(pdf_cmap **cmapp, char *name) pdf_logfont("}\n"); *cmapp = cmap; - return nil; + return fz_okay; cleanup: if (cmap) @@ -1136,31 +1225,31 @@ pdf_newidentitycmap(pdf_cmap **cmapp, int wmode, int bytes) error = pdf_newcmap(&cmap); if (error) - return error; + return fz_rethrow(error, "cannot create cmap"); sprintf(cmap->cmapname, "Identity-%c", wmode ? 'V' : 'H'); error = pdf_addcodespace(cmap, 0x0000, 0xffff, bytes); if (error) { pdf_dropcmap(cmap); - return error; + return fz_rethrow(error, "cannot add code space"); } error = pdf_maprangetorange(cmap, 0x0000, 0xffff, 0); if (error) { pdf_dropcmap(cmap); - return error; + return fz_rethrow(error, "cannot map <0000> to <ffff>"); } error = pdf_sortcmap(cmap); if (error) { pdf_dropcmap(cmap); - return error; + return fz_rethrow(error, "cannot sort cmap"); } pdf_setwmode(cmap, wmode); *cmapp = cmap; - return nil; + return fz_okay; } diff --git a/mupdf/pdf_colorspace1.c b/mupdf/pdf_colorspace1.c index 3cb5c95c..7c79f79a 100644 --- a/mupdf/pdf_colorspace1.c +++ b/mupdf/pdf_colorspace1.c @@ -534,8 +534,8 @@ loadseparation(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) } initcs((fz_colorspace*)cs, - n == 1 ? "Separation" : "DeviceN", n, - separationtoxyz, nil, dropseparation); + n == 1 ? "Separation" : "DeviceN", n, + separationtoxyz, nil, dropseparation); cs->base = base; cs->tint = tint; diff --git a/mupdf/pdf_colorspace2.c b/mupdf/pdf_colorspace2.c index 9e792b00..028628a1 100644 --- a/mupdf/pdf_colorspace2.c +++ b/mupdf/pdf_colorspace2.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* * Optimized color conversions for Device colorspaces diff --git a/mupdf/pdf_crypt.c b/mupdf/pdf_crypt.c index dd13ed9a..2fac478f 100644 --- a/mupdf/pdf_crypt.c +++ b/mupdf/pdf_crypt.c @@ -52,7 +52,7 @@ static void padpassword(unsigned char *buf, char *pw, int pwlen) fz_error * pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id) { - pdf_crypt *crypt = nil; + pdf_crypt *crypt; fz_obj *obj; int m; @@ -65,7 +65,7 @@ pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id) crypt = fz_malloc(sizeof(pdf_crypt)); if (!crypt) - return fz_outofmem; + return fz_throw("outofmem: crypt struct"); crypt->encrypt = fz_keepobj(enc); crypt->id = nil; @@ -116,7 +116,7 @@ pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id) memset(crypt->key, 0, 16); *cp = crypt; - return nil; + return fz_okay; cleanup: pdf_dropcrypt(crypt); @@ -288,7 +288,7 @@ pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj crypt = fz_malloc(sizeof(pdf_crypt)); if (!crypt) - return fz_outofmem; + return fz_throw("outofmem: crypt struct"); crypt->encrypt = nil; crypt->id = fz_keepobj(fz_arrayget(id, 0)); @@ -302,10 +302,10 @@ pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj error = fz_packobj(&crypt->encrypt, "<< /Filter /Standard " - "/V %i /R %i " - "/O %# /U %# " - "/P %i " - "/Length %i >>", + "/V %i /R %i " + "/O %# /U %# " + "/P %i " + "/Length %i >>", crypt->r == 2 ? 1 : 2, crypt->r, crypt->o, 32, @@ -315,30 +315,29 @@ pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj if (error) { pdf_dropcrypt(crypt); - return error; + return fz_rethrow(error, "cannot create encryption dictionary"); } *cp = crypt; - return nil; + return fz_okay; } /* * Algorithm 3.6 Checking the user password + * + * Return true if the password is valid. */ -fz_error * +int pdf_setpassword(pdf_crypt *crypt, char *pw) { - fz_error *error = pdf_setuserpassword(crypt, pw, strlen(pw)); - if (error) - { - fz_droperror(error); - error = pdf_setownerpassword(crypt, pw, strlen(pw)); - } - return error; + int okay = pdf_setuserpassword(crypt, pw, strlen(pw)); + if (!okay) + okay = pdf_setownerpassword(crypt, pw, strlen(pw)); + return okay; } -fz_error * +int pdf_setuserpassword(pdf_crypt *crypt, char *userpw, int pwlen) { unsigned char saved[32]; @@ -350,12 +349,11 @@ pdf_setuserpassword(pdf_crypt *crypt, char *userpw, int pwlen) memcpy(crypt->u, saved, 32); if (memcmp(test, saved, crypt->r == 3 ? 16 : 32) != 0) - return fz_throw("invalid password"); - - return nil; + return 0; + return 1; } -fz_error * +int pdf_setownerpassword(pdf_crypt *crypt, char *ownerpw, int pwlen) { unsigned char buf[32]; @@ -398,7 +396,7 @@ pdf_setownerpassword(pdf_crypt *crypt, char *ownerpw, int pwlen) } } - return pdf_setuserpassword(crypt, (char *) buf, 32); + return pdf_setuserpassword(crypt, buf, 32); } /* @@ -414,7 +412,7 @@ pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid) if (fz_isstring(obj)) { - s = (unsigned char *) fz_tostrbuf(obj); + s = fz_tostrbuf(obj); n = fz_tostrlen(obj); createobjkey(crypt, oid, gid, key); fz_arc4init(&arc4, key, crypt->keylen); @@ -446,8 +444,12 @@ pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid) fz_error * pdf_cryptstream(fz_filter **fp, pdf_crypt *crypt, int oid, int gid) { + fz_error *error; unsigned char key[16]; createobjkey(crypt, oid, gid, key); - return fz_newarc4filter(fp, key, crypt->keylen); + error = fz_newarc4filter(fp, key, crypt->keylen); + if (error) + return fz_rethrow(error, "cannot create crypt filter"); + return fz_okay; } diff --git a/mupdf/pdf_debug.c b/mupdf/pdf_debug.c index 4704794b..aafc4e9c 100644 --- a/mupdf/pdf_debug.c +++ b/mupdf/pdf_debug.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* * Enable logging by setting environment variable MULOG to: diff --git a/mupdf/pdf_doctor.c b/mupdf/pdf_doctor.c index 99d9ff85..97e96479 100644 --- a/mupdf/pdf_doctor.c +++ b/mupdf/pdf_doctor.c @@ -1,8 +1,10 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* * Sweep and mark reachable objects + * + * Don't bother chaining errors for this deep recursion */ static fz_error *sweepref(pdf_xref *xref, fz_obj *ref); @@ -36,7 +38,7 @@ sweepobj(pdf_xref *xref, fz_obj *obj) if (fz_isindirect(obj)) return sweepref(xref, obj); - return nil; + return fz_okay; } static fz_error * @@ -49,16 +51,16 @@ sweepref(pdf_xref *xref, fz_obj *ref) oid = fz_tonum(ref); if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object number out of range"); + return fz_throw("object out of range %d", oid); if (xref->table[oid].mark) - return nil; + return fz_okay; xref->table[oid].mark = 1; error = pdf_loadindirect(&obj, xref, ref); if (error) - return error; + return fz_rethrow(error, "cannot load indirect object"); error = sweepobj(xref, obj); if (error) @@ -68,7 +70,7 @@ sweepref(pdf_xref *xref, fz_obj *ref) } fz_dropobj(obj); - return nil; + return fz_okay; } /* @@ -89,7 +91,7 @@ pdf_garbagecollect(pdf_xref *xref) error = sweepobj(xref, xref->trailer); if (error) - return error; + return fz_rethrow(error, "cannot mark used objects"); for (i = 0; i < xref->len; i++) { @@ -98,12 +100,16 @@ pdf_garbagecollect(pdf_xref *xref) if (x->type == 'o') g = 0; if (!x->mark && x->type != 'f' && x->type != 'd') - pdf_deleteobject(xref, i, g); + { + error = pdf_deleteobject(xref, i, g); + if (error) + return fz_rethrow(error, "cannot delete unmarked object %d", i); + } } pdf_logxref("}\n"); - return nil; + return fz_okay; } /* @@ -129,14 +135,18 @@ remaprefs(fz_obj **newp, fz_obj *old, struct pair *map, int n) g = fz_togen(old); for (i = 0; i < n; i++) if (map[i].soid == o && map[i].sgen == g) - return fz_newindirect(newp, map[i].doid, map[i].dgen); + { + error = fz_newindirect(newp, map[i].doid, map[i].dgen); + if (error) + return fz_rethrow(error, "cannot remap indirect reference"); + } } else if (fz_isarray(old)) { error = fz_newarray(newp, fz_arraylen(old)); if (error) - return error; + return fz_rethrow(error, "cannot remap array"); for (i = 0; i < fz_arraylen(old); i++) { tmp = fz_arrayget(old, i); @@ -154,7 +164,7 @@ remaprefs(fz_obj **newp, fz_obj *old, struct pair *map, int n) { error = fz_newdict(newp, fz_dictlen(old)); if (error) - return error; + return fz_rethrow(error, "cannot remap dictionary"); for (i = 0; i < fz_dictlen(old); i++) { key = fz_dictgetkey(old, i); @@ -174,11 +184,11 @@ remaprefs(fz_obj **newp, fz_obj *old, struct pair *map, int n) *newp = fz_keepobj(old); } - return nil; + return fz_okay; cleanup: fz_dropobj(*newp); - return error; + return fz_rethrow(error, "cannot remap object"); } /* @@ -202,9 +212,9 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) error = sweepobj(src, root); if (error) - return error; + return fz_rethrow(error, "cannot mark used objects"); - for (n = 0, i = 0; i < src->len; i++) + for (n = 0, i = 0; i < src->len; i++) if (src->table[i].mark) n++; @@ -212,9 +222,9 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) map = fz_malloc(sizeof(struct pair) * n); if (!map) - return fz_outofmem; + return fz_throw("outofmem: remapping table"); - for (n = 0, i = 0; i < src->len; i++) + for (n = 0, i = 0; i < src->len; i++) { if (src->table[i].mark) { @@ -229,15 +239,15 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) } } - error = remaprefs(newp, root, map, n); + error == remaprefs(newp, root, map, n); if (error) goto cleanup; - for (i = 0; i < n; i++) + for (i = 0; i < n; i++) { pdf_logxref("copyfrom %d %d to %d %d\n", - map[i].soid, map[i].sgen, - map[i].doid, map[i].dgen); + map[i].soid, map[i].sgen, + map[i].doid, map[i].dgen); error = pdf_loadobject(&old, src, map[i].soid, map[i].sgen); if (error) @@ -257,8 +267,10 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) if (error) goto cleanup; - pdf_updateobject(dst, map[i].doid, map[i].dgen, new); + error = pdf_updateobject(dst, map[i].doid, map[i].dgen, new); fz_dropobj(new); + if (error) + goto cleanup; } pdf_logxref("}\n"); @@ -268,6 +280,6 @@ pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *root) cleanup: fz_free(map); - return error; + return fz_rethrow(error, "cannot transplant objects"); } diff --git a/mupdf/pdf_font.c b/mupdf/pdf_font.c index 08de54e2..a2386fed 100644 --- a/mupdf/pdf_font.c +++ b/mupdf/pdf_font.c @@ -9,32 +9,32 @@ static char *basefontnames[14][7] = { - { "Courier", "CourierNew", "CourierNewPSMT", 0 }, - { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", - "CourierNewPS-BoldMT", "CourierNew-Bold", 0 }, - { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", - "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 }, - { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", - "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 }, - { "Helvetica", "ArialMT", "Arial", 0 }, - { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", - "Helvetica,Bold", 0 }, - { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", - "Helvetica,Italic", "Helvetica-Italic", 0 }, - { "Helvetica-BoldOblique", "Arial-BoldItalicMT", - "Arial,BoldItalic", "Arial-BoldItalic", - "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 }, - { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", - "TimesNewRomanPS", 0 }, - { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", - "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 }, - { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", - "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 }, - { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", - "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", - "TimesNewRoman-BoldItalic", 0 }, - { "Symbol", 0 }, - { "ZapfDingbats", 0 } + { "Courier", "CourierNew", "CourierNewPSMT", 0 }, + { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", + "CourierNewPS-BoldMT", "CourierNew-Bold", 0 }, + { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", + "CourierNewPS-ItalicMT", "CourierNew-Italic", 0 }, + { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", + "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", 0 }, + { "Helvetica", "ArialMT", "Arial", 0 }, + { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", + "Helvetica,Bold", 0 }, + { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", + "Helvetica,Italic", "Helvetica-Italic", 0 }, + { "Helvetica-BoldOblique", "Arial-BoldItalicMT", + "Arial,BoldItalic", "Arial-BoldItalic", + "Helvetica,BoldItalic", "Helvetica-BoldItalic", 0 }, + { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", + "TimesNewRomanPS", 0 }, + { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", + "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", 0 }, + { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", + "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", 0 }, + { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", + "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", + "TimesNewRoman-BoldItalic", 0 }, + { "Symbol", 0 }, + { "ZapfDingbats", 0 } }; /* @@ -107,7 +107,7 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) FT_Set_Char_Size(face, 1000, 1000, 72, 72); fterr = FT_Load_Glyph(font->ftface, gid, - FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); + FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); if (fterr) return fz_throw("freetype failed to load glyph: 0x%x", fterr); @@ -517,7 +517,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) font->cidtogid = etable; error = pdf_loadtounicode(font, xref, - estrings, nil, fz_dictgets(dict, "ToUnicode")); + estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; @@ -966,8 +966,8 @@ pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *colle bbox = pdf_torect(fz_dictgets(desc, "FontBBox")); pdf_logfont("bbox [%g %g %g %g]\n", - bbox.x0, bbox.y0, - bbox.x1, bbox.y1); + bbox.x0, bbox.y0, + bbox.x1, bbox.y1); pdf_logfont("flags %d\n", font->flags); diff --git a/mupdf/pdf_fontagl.c b/mupdf/pdf_fontagl.c index d4ce0540..8929c14d 100644 --- a/mupdf/pdf_fontagl.c +++ b/mupdf/pdf_fontagl.c @@ -4585,62 +4585,63 @@ static const unsigned short agldat[4368] = { int pdf_lookupagl(char *name, int *ucsbuf, int ucscap) { - char buf[256]; - int ucslen = 0; - char *p; - char *s; - int i; + char buf[256]; + int ucslen = 0; + char *p; + char *s; + int i; - strlcpy(buf, name, sizeof buf); + strlcpy(buf, name, sizeof buf); - /* kill anything after first period */ - p = strchr(buf, '.'); - if (p) - p[0] = 0; + /* kill anything after first period */ + p = strchr(buf, '.'); + if (p) + p[0] = 0; - /* split into components separated by underscore */ - p = buf; - s = strsep(&p, "_"); - while (s) - { - int l = 0; - int r = nelem(aglidx) - 1; + /* split into components separated by underscore */ + p = buf; + s = strsep(&p, "_"); + while (s) + { + int l = 0; + int r = nelem(aglidx) - 1; - while (l <= r) - { - int m = (l + r) >> 1; - int c = strcmp(s, aglidx[m].name); - if (c < 0) - r = m - 1; - else if (c > 0) - l = m + 1; - else - { - for (i = 0; i < aglidx[m].num; i++) - ucsbuf[ucslen++] = agldat[aglidx[m].ofs + i]; - goto next; - } - } + while (l <= r) + { + int m = (l + r) >> 1; + int c = strcmp(s, aglidx[m].name); + if (c < 0) + r = m - 1; + else if (c > 0) + l = m + 1; + else + { + for (i = 0; i < aglidx[m].num; i++) + ucsbuf[ucslen++] = agldat[aglidx[m].ofs + i]; + goto next; + } + } - if (strstr(s, "uni") == s) - { - char tmp[5]; - s += 3; - while (s[0]) - { - strlcpy(tmp, s, 5); - ucsbuf[ucslen++] = strtol(tmp, 0, 16); - s += MIN(strlen(s), 4); - } - } + if (strstr(s, "uni") == s) + { + char tmp[5]; + s += 3; + while (s[0]) + { + strlcpy(tmp, s, 5); + ucsbuf[ucslen++] = strtol(tmp, 0, 16); + s += MIN(strlen(s), 4); + } + } - else if (strstr(s, "u") == s) - ucsbuf[ucslen++] = strtol(s + 1, 0, 16); + else if (strstr(s, "u") == s) + ucsbuf[ucslen++] = strtol(s + 1, 0, 16); next: - s = strsep(&p, "_"); - } + s = strsep(&p, "_"); + } - return ucslen; + return ucslen; } + diff --git a/mupdf/pdf_fontenc.c b/mupdf/pdf_fontenc.c index d3726675..d45f4edb 100644 --- a/mupdf/pdf_fontenc.c +++ b/mupdf/pdf_fontenc.c @@ -2,8 +2,8 @@ * Built-in font tables */ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" #define _notdef 0 diff --git a/mupdf/pdf_fontfile.c b/mupdf/pdf_fontfile.c index b90c71c0..868b0341 100644 --- a/mupdf/pdf_fontfile.c +++ b/mupdf/pdf_fontfile.c @@ -1,7 +1,7 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" -#include <mupdf/base14.h> +#include "mupdf/base14.h" #include <ft2build.h> #include FT_FREETYPE_H @@ -26,8 +26,7 @@ static const struct const char *name; const unsigned char *cff; const unsigned int *len; -} basefonts[15] = -{ +} basefonts[15] = { { "Courier", fonts_NimbusMonL_Regu_cff, &fonts_NimbusMonL_Regu_cff_len }, @@ -127,7 +126,7 @@ static fz_error *initfontlibs(void) if (maj == 2 && min == 1 && pat < 7) return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); - return nil; + return fz_okay; } fz_error * @@ -141,13 +140,13 @@ pdf_loadbuiltinfont(pdf_font *font, char *fontname) error = initfontlibs(); if (error) - return error; + return fz_rethrow(error, "cannot init font libraries"); for (i = 0; i < 15; i++) if (!strcmp(fontname, basefonts[i].name)) goto found; - return fz_throw("font not found: %s", fontname); + return fz_throw("cannot find font: %s", fontname); found: pdf_logfont("load builtin font %s\n", fontname); @@ -157,9 +156,9 @@ found: e = FT_New_Memory_Face(ftlib, data, len, 0, (FT_Face*)&font->ftface); if (e) - return fz_throw("freetype: could not load font: 0x%x", e); + return fz_throw("freetype: cannot load font: 0x%x", e); - return nil; + return fz_okay; } static int @@ -245,13 +244,13 @@ loadcidfont(pdf_font *font, int csi, int kind) pdf_logfont("load system font '%s'\n", fontsubs[i].name); e = FT_New_Face(ftlib, path, 0, (FT_Face*)&font->ftface); if (e) - return fz_throw("freetype: could not load font: 0x%x", e); - return nil; + return fz_throw("freetype: cannot load font: 0x%x", e); + return fz_okay; } } } - return fz_throw("could not find cid font file"); + return fz_throw("cannot find cid font file"); } fz_error * @@ -268,7 +267,7 @@ pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) error = initfontlibs(); if (error) - return error; + return fz_rethrow(error, "cannot init font libraries"); font->substitute = 1; @@ -291,7 +290,7 @@ pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) isbold = 1; pdf_logfont("fixed-%d serif-%d italic-%d script-%d bold-%d\n", - isfixed, isserif, isitalic, isscript, isbold); + isfixed, isserif, isitalic, isscript, isbold); if (collection) { @@ -355,7 +354,11 @@ pdf_loadsystemfont(pdf_font *font, char *fontname, char *collection) } } - return pdf_loadbuiltinfont(font, name); + error = pdf_loadbuiltinfont(font, name); + if (error) + return fz_throw("cannot load builtin substitute font: %s", name); + + return fz_okay; } fz_error * @@ -368,24 +371,24 @@ pdf_loadembeddedfont(pdf_font *font, pdf_xref *xref, fz_obj *stmref) error = initfontlibs(); if (error) - return error; + return fz_rethrow(error, "cannot init font libraries"); pdf_logfont("load embedded font\n"); error = pdf_loadstream(&buf, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) - return error; + return fz_rethrow(error, "cannot load font stream"); fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face); - - if (fterr) { - fz_free(buf); - return fz_throw("freetype could not load embedded font: 0x%x", fterr); + if (fterr) + { + fz_dropbuffer(buf); + return fz_throw("freetype: cannot load embedded font: 0x%x", fterr); } font->ftface = face; font->fontdata = buf; - return nil; + return fz_okay; } diff --git a/mupdf/pdf_fontfilems.c b/mupdf/pdf_fontfilems.c index f37d8668..b30bbdec 100644 --- a/mupdf/pdf_fontfilems.c +++ b/mupdf/pdf_fontfilems.c @@ -610,10 +610,10 @@ pdf_createfontlistMS() removeredundancy(&fontlistMS); - return nil; - cleanup: - fz_abort(err); + if(err) + fz_abort(err); + return nil; } void @@ -644,7 +644,7 @@ pdf_lookupfontMS(char *fontname, char **fontpath, int *index) strlcpy(fontmap.fontface,pattern,sizeof(fontmap.fontface)); found = localbsearch(&fontmap,fontlistMS.fontmap,fontlistMS.len, - sizeof(pdf_fontmapMS),compare); + sizeof(pdf_fontmapMS),compare); if(found) { diff --git a/mupdf/pdf_function.c b/mupdf/pdf_function.c index c6cfd9a6..76142d8b 100644 --- a/mupdf/pdf_function.c +++ b/mupdf/pdf_function.c @@ -1,7 +1,7 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" -/* this mess is seokgyo's */ +/* this mess is seokgyo's doing */ enum { @@ -60,21 +60,15 @@ struct pdf_function_s } u; }; +/* + * PostScript calculator + */ + #define RADIAN 57.2957795 #define LERP(x, xmin, xmax, ymin, ymax) \ (ymin) + ((x) - (xmin)) * ((ymax) - (ymin)) / ((xmax) - (xmin)) -#define SAFE_PUSHINT(st, a) {error = pspushint(st, a); if (error) goto cleanup;} -#define SAFE_PUSHREAL(st, a) {error = pspushreal(st, a); if (error) goto cleanup;} -#define SAFE_PUSHBOOL(st, a) {error = pspushbool(st, a); if (error) goto cleanup;} -#define SAFE_POPINT(st, a) {error = pspopint(st, a); if (error) goto cleanup;} -#define SAFE_POPNUM(st, a) {error = pspopnum(st, a); if (error) goto cleanup;} -#define SAFE_POPBOOL(st, a) {error = pspopbool(st, a); if (error) goto cleanup;} -#define SAFE_POP(st) {error = pspop(st); if (error) goto cleanup;} -#define SAFE_INDEX(st, i) {error = psindex(st, i); if (error) goto cleanup;} -#define SAFE_COPY(st, n) {error = pscopy(st, n); if (error) goto cleanup;} - enum { PSBOOL, PSINT, PSREAL, PSOPERATOR, PSBLOCK }; enum @@ -111,15 +105,11 @@ struct psobj_s } u; }; -/* - * PostScript calculator - */ - enum { PSSTACKSIZE = 100 }; -#define fz_stackoverflow fz_throw("rangecheck: stackoverflow in calculator") -#define fz_stackunderflow fz_throw("rangecheck: stackunderflow in calculator") -#define fz_stacktypemismatch fz_throw("typecheck: postscript calculator") +#define fz_stackoverflow fz_throw("stack overflow in calculator function") +#define fz_stackunderflow fz_throw("stack underflow in calculator function") +#define fz_stacktypemismatch fz_throw("type mismatch in calculator function") typedef struct psstack_s psstack; @@ -149,95 +139,74 @@ pscheckunderflow(psstack *st) } static int -pschecktype(psstack *st, unsigned short t1, unsigned short t2) +pschecktype(psstack *st, unsigned short type) { - return (st->stack[st->sp].type == t1 || - st->stack[st->sp].type == t2); + return st->stack[st->sp].type == type; } static fz_error * pspushbool(psstack *st, int booln) { - if (pscheckoverflow(st, 1)) - { - st->stack[--st->sp].type = PSBOOL; - st->stack[st->sp].u.b = booln; - } - else + if (!pscheckoverflow(st, 1)) return fz_stackoverflow; - return nil; + st->stack[--st->sp].type = PSBOOL; + st->stack[st->sp].u.b = booln; + return fz_okay; } static fz_error * pspushint(psstack *st, int intg) { - if (pscheckoverflow(st, 1)) - { - st->stack[--st->sp].type = PSINT; - st->stack[st->sp].u.i = intg; - } - else + if (!pscheckoverflow(st, 1)) return fz_stackoverflow; - return nil; + st->stack[--st->sp].type = PSINT; + st->stack[st->sp].u.i = intg; + return fz_okay; } static fz_error * pspushreal(psstack *st, float real) { - if (pscheckoverflow(st, 1)) - { - st->stack[--st->sp].type = PSREAL; - st->stack[st->sp].u.f = real; - } - else + if (!pscheckoverflow(st, 1)) return fz_stackoverflow; - return nil; + st->stack[--st->sp].type = PSREAL; + st->stack[st->sp].u.f = real; + return fz_okay; } static fz_error * pspopbool(psstack *st, int *booln) { - if (pscheckunderflow(st) && pschecktype(st, PSBOOL, PSBOOL)) - { - *booln = st->stack[st->sp++].u.b; - } - else if (pscheckunderflow(st)) + if (!pscheckunderflow(st)) return fz_stackunderflow; - else + if (!pschecktype(st, PSBOOL)) return fz_stacktypemismatch; - return nil; + *booln = st->stack[st->sp++].u.b; + return fz_okay; } static fz_error * pspopint(psstack *st, int *intg) { - if (pscheckunderflow(st) && pschecktype(st, PSINT, PSINT)) - { - *intg = st->stack[st->sp++].u.i; - } - else if (pscheckunderflow(st)) + if (!pscheckunderflow(st)) return fz_stackunderflow; - else + if (!pschecktype(st, PSINT)) return fz_stacktypemismatch; - return nil; + *intg = st->stack[st->sp++].u.i; + return fz_okay; } static fz_error * pspopnum(psstack *st, float *real) { - if (pscheckunderflow(st) && pschecktype(st, PSINT, PSREAL)) - { - float ret; - ret = (st->stack[st->sp].type == PSINT) ? - (float) st->stack[st->sp].u.i : st->stack[st->sp].u.f; - ++st->sp; - *real = ret; - } - else if (pscheckunderflow(st)) + if (!pscheckunderflow(st)) return fz_stackunderflow; - else + if (!pschecktype(st, PSINT) && !pschecktype(st, PSREAL)) return fz_stacktypemismatch; - return nil; + *real = (st->stack[st->sp].type == PSINT) ? + st->stack[st->sp].u.i : st->stack[st->sp].u.f; + ++st->sp; + return fz_okay; } static int @@ -250,8 +219,8 @@ static int pstoptwoareints(psstack *st) { return st->sp < PSSTACKSIZE - 1 && - st->stack[st->sp].type == PSINT && - st->stack[st->sp + 1].type == PSINT; + st->stack[st->sp].type == PSINT && + st->stack[st->sp + 1].type == PSINT; } static int @@ -264,8 +233,8 @@ static int pstoptwoarenums(psstack *st) { return st->sp < PSSTACKSIZE - 1 && - (st->stack[st->sp].type == PSINT || st->stack[st->sp].type == PSREAL) && - (st->stack[st->sp + 1].type == PSINT || st->stack[st->sp + 1].type == PSREAL); + (st->stack[st->sp].type == PSINT || st->stack[st->sp].type == PSREAL) && + (st->stack[st->sp + 1].type == PSINT || st->stack[st->sp + 1].type == PSREAL); } static fz_error * @@ -282,7 +251,7 @@ pscopy(psstack *st, int n) } st->sp -= n; - return nil; + return fz_okay; } static void @@ -309,6 +278,7 @@ psroll(psstack *st, int n, int j) } for (i = 0; i < j; ++i) { + /* FIXME check for underflow? */ obj = st->stack[st->sp]; for (k = st->sp; k < st->sp + n - 1; ++k) { @@ -322,23 +292,19 @@ static fz_error * psindex(psstack *st, int i) { if (!pscheckoverflow(st, 1)) - { return fz_stackoverflow; - } --st->sp; st->stack[st->sp] = st->stack[st->sp + 1 + i]; - return nil; + return fz_okay; } static fz_error * pspop(psstack *st) { if (!pscheckoverflow(st, 1)) - { return fz_stackoverflow; - } ++st->sp; - return nil; + return fz_okay; } static fz_error * @@ -350,19 +316,18 @@ resizecode(pdf_function *func, int newsize) psobj *newcode; newcode = fz_realloc(func->u.p.code, newcodecap * sizeof(psobj)); if (!newcode) - return fz_outofmem; + return fz_throw("outofmem: calculator function code"); func->u.p.cap = newcodecap; func->u.p.code = newcode; } - return nil; + return fz_okay; } static fz_error * parsecode(pdf_function *func, fz_stream *stream, int *codeptr) { - fz_error *error = nil; - unsigned char buf[64]; - int buflen = sizeof(buf) / sizeof(buf[0]); + fz_error *error; + char buf[64]; int len; int token; int opptr, elseptr; @@ -372,62 +337,80 @@ parsecode(pdf_function *func, fz_stream *stream, int *codeptr) while (1) { - token = pdf_lex(stream, buf, buflen, &len); - - if (token == PDF_TERROR || token == PDF_TEOF) - goto cleanup; + error = pdf_lex(&token, stream, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "calculator function lexical error"); switch(token) { + case PDF_TEOF: + return fz_throw("truncated calculator function"); + case PDF_TINT: - resizecode(func, *codeptr); + error = resizecode(func, *codeptr); + if (error) + return fz_rethrow(error, "resize calculator function code"); func->u.p.code[*codeptr].type = PSINT; - func->u.p.code[*codeptr].u.i = atoi((char *) buf); + func->u.p.code[*codeptr].u.i = atoi(buf); ++*codeptr; break; case PDF_TREAL: - resizecode(func, *codeptr); + error = resizecode(func, *codeptr); + if (error) + return fz_rethrow(error, "resize calculator function code"); func->u.p.code[*codeptr].type = PSREAL; - func->u.p.code[*codeptr].u.f = atof((char *) buf); + func->u.p.code[*codeptr].u.f = atof(buf); ++*codeptr; break; case PDF_TOBRACE: opptr = *codeptr; *codeptr += 3; - resizecode(func, opptr + 2); - error = parsecode(func, stream, codeptr); - if (error) goto cleanup; - token = pdf_lex(stream, buf, buflen, &len); + error = resizecode(func, opptr + 2); + if (error) + return fz_rethrow(error, "resize calculator function code"); + + error = parsecode(func, stream, codeptr); + if (error) + return fz_rethrow(error, "error in 'if' branch"); - if (token == PDF_TEOF || token == PDF_TERROR) - goto cleanup; + error = pdf_lex(&token, stream, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "calculator function syntax error"); - if (token == PDF_TOBRACE) { + if (token == PDF_TOBRACE) + { elseptr = *codeptr; error = parsecode(func, stream, codeptr); - if (error) goto cleanup; - token = pdf_lex(stream, buf, buflen, &len); - if (token == PDF_TERROR || token == PDF_TEOF) - goto cleanup; + if (error) + return fz_rethrow(error, "error in 'else' branch"); + + error = pdf_lex(&token, stream, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "calculator function syntax error"); } - else + else + { elseptr = -1; + } - if (token == PDF_TKEYWORD) { - if (!strcmp((char *) buf, "if")) { + if (token == PDF_TKEYWORD) + { + if (!strcmp(buf, "if")) + { if (elseptr >= 0) - goto cleanup; + return fz_throw("too many branches for 'if'"); func->u.p.code[opptr].type = PSOPERATOR; func->u.p.code[opptr].u.op = PSOIF; func->u.p.code[opptr+2].type = PSBLOCK; func->u.p.code[opptr+2].u.block = *codeptr; } - else if (!strcmp((char *) buf, "ifelse")) { + else if (!strcmp(buf, "ifelse")) + { if (elseptr < 0) - goto cleanup; + return fz_throw("not enough branches for 'ifelse'"); func->u.p.code[opptr].type = PSOPERATOR; func->u.p.code[opptr].u.op = PSOIFELSE; func->u.p.code[opptr+1].type = PSBLOCK; @@ -436,91 +419,107 @@ parsecode(pdf_function *func, fz_stream *stream, int *codeptr) func->u.p.code[opptr+2].u.block = *codeptr; } else - goto cleanup; + { + return fz_throw("unknown keyword in 'if-else' context: '%s'", buf); + } } else - goto cleanup; + { + return fz_throw("missing keyword in 'if-else' context"); + } break; case PDF_TCBRACE: - resizecode(func, *codeptr); + error = resizecode(func, *codeptr); + if (error) + return fz_rethrow(error, "resize calculator function code"); func->u.p.code[*codeptr].type = PSOPERATOR; func->u.p.code[*codeptr].u.op = PSORETURN; ++*codeptr; - return nil; + return fz_okay; case PDF_TKEYWORD: + cmp = -1; a = -1; b = sizeof(psopnames) / sizeof(psopnames[0]); - /* invariant: psopnames[a] < op < psopnames[b] */ - while (b - a > 1) { + while (b - a > 1) + { mid = (a + b) / 2; - cmp = strcmp((char *) buf, psopnames[mid]); - if (cmp > 0) { + cmp = strcmp(buf, psopnames[mid]); + if (cmp > 0) a = mid; - } else if (cmp < 0) { + else if (cmp < 0) b = mid; - } else { + else a = b = mid; - } } if (cmp != 0) - goto cleanup; + return fz_throw("unknown operator: '%s'", buf); + + error = resizecode(func, *codeptr); + if (error) + return fz_rethrow(error, "resize calculator function code"); - resizecode(func, *codeptr); func->u.p.code[*codeptr].type = PSOPERATOR; func->u.p.code[*codeptr].u.op = a; ++*codeptr; break; default: - goto cleanup; + return fz_throw("calculator function syntax error"); } } - return nil; - -cleanup: - if (error) return error; - return fz_throw("syntaxerror: postscript calculator"); } static fz_error * loadpostscriptfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen) { - fz_error *error = nil; + fz_error *error; fz_stream *stream; int codeptr; pdf_logrsrc("load postscript function %d %d\n", oid, gen); error = pdf_openstream(&stream, xref, oid, gen); - if (error) goto cleanup; + if (error) + return fz_rethrow(error, "cannot open calculator function stream"); if (fz_readbyte(stream) != '{') - goto cleanup; + { + fz_dropstream(stream); + return fz_throw("stream is not a calculator function"); + } func->u.p.code = nil; func->u.p.cap = 0; - codeptr = 0; error = parsecode(func, stream, &codeptr); - if (error) goto cleanup; - - fz_dropstream(stream); - - return nil; + if (error) + { + fz_dropstream(stream); + return fz_rethrow(error, "cannot parse calculator function"); + } -cleanup: fz_dropstream(stream); - if (error) return error; - return fz_throw("syntaxerror: postscript calculator"); + return fz_okay; } +#define SAFE_RETHROW if (error) fz_rethrow(error, "runtime error in calculator function") +#define SAFE_PUSHINT(st, a) { error = pspushint(st, a); SAFE_RETHROW; } +#define SAFE_PUSHREAL(st, a) { error = pspushreal(st, a); SAFE_RETHROW; } +#define SAFE_PUSHBOOL(st, a) { error = pspushbool(st, a); SAFE_RETHROW; } +#define SAFE_POPINT(st, a) { error = pspopint(st, a); SAFE_RETHROW; } +#define SAFE_POPNUM(st, a) { error = pspopnum(st, a); SAFE_RETHROW; } +#define SAFE_POPBOOL(st, a) { error = pspopbool(st, a); SAFE_RETHROW; } +#define SAFE_POP(st) { error = pspop(st); SAFE_RETHROW; } +#define SAFE_INDEX(st, i) { error = psindex(st, i); SAFE_RETHROW; } +#define SAFE_COPY(st, n) { error = pscopy(st, n); SAFE_RETHROW; } + static fz_error * evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) { - fz_error *error = nil; + fz_error *error; int i1, i2; float r1, r2; int b1, b2; @@ -544,7 +543,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) if (pstopisint(st)) { SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, abs(i1)); - } else { + } + else { SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, fabs(r1)); } @@ -555,7 +555,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, i1 + i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, r1 + r2); @@ -567,7 +568,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, i1 & i2); - } else { + } + else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); SAFE_PUSHBOOL(st, b1 && b2); @@ -585,9 +587,11 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i1); if (i2 > 0) { SAFE_PUSHINT(st, i1 << i2); - } else if (i2 < 0) { + } + else if (i2 < 0) { SAFE_PUSHINT(st, (int)((unsigned int)i1 >> i2)); - } else { + } + else { SAFE_PUSHINT(st, i1); } break; @@ -638,11 +642,13 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 == i2); - } else if (pstoptwoarenums(st)) { + } + else if (pstoptwoarenums(st)) { SAFE_POPNUM(st, &r1); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 == r2); - } else { + } + else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b2); SAFE_PUSHBOOL(st, b1 == b2); @@ -675,7 +681,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 >= i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 >= r2); @@ -687,7 +694,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 > i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 > r2); @@ -710,7 +718,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 <= i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 <= r2); @@ -732,7 +741,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 < i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 < r2); @@ -749,9 +759,10 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) if (pstoptwoareints(st)) { SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); - /*~ should check for out-of-range, and push a real instead */ + /* FIXME should check for out-of-range, and push a real instead */ SAFE_PUSHINT(st, i1 * i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, r1 * r2); @@ -763,11 +774,13 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHBOOL(st, i1 != i2); - } else if (pstoptwoarenums(st)) { + } + else if (pstoptwoarenums(st)) { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHBOOL(st, r1 != r2); - } else { + } + else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); SAFE_PUSHBOOL(st, b1 != b2); @@ -778,7 +791,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) if (pstopisint(st)) { SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, -i1); - } else { + } + else { SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, -r1); } @@ -788,7 +802,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) if (pstopisint(st)) { SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, ~i1); - } else { + } + else { SAFE_POPBOOL(st, &b1); SAFE_PUSHBOOL(st, !b1); } @@ -799,7 +814,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, i1 | i2); - } else { + } + else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); SAFE_PUSHBOOL(st, b1 || b2); @@ -838,7 +854,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, i1 - i2); - } else { + } + else { SAFE_POPNUM(st, &r2); SAFE_POPNUM(st, &r1); SAFE_PUSHREAL(st, r1 - r2); @@ -861,7 +878,8 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) SAFE_POPINT(st, &i2); SAFE_POPINT(st, &i1); SAFE_PUSHINT(st, i1 ^ i2); - } else { + } + else { SAFE_POPBOOL(st, &b2); SAFE_POPBOOL(st, &b1); SAFE_PUSHBOOL(st, b1 ^ b2); @@ -871,7 +889,9 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) case PSOIF: SAFE_POPBOOL(st, &b1); if (b1) { - evalpostscriptfunc(func, st, codeptr + 2); + error = evalpostscriptfunc(func, st, codeptr + 2); + if (error) + return fz_rethrow(error, "runtime error in if-branch"); } codeptr = func->u.p.code[codeptr + 1].u.block; break; @@ -879,26 +899,30 @@ evalpostscriptfunc(pdf_function *func, psstack *st, int codeptr) case PSOIFELSE: SAFE_POPBOOL(st, &b1); if (b1) { - evalpostscriptfunc(func, st, codeptr + 2); - } else { - evalpostscriptfunc(func, st, func->u.p.code[codeptr].u.block); + error = evalpostscriptfunc(func, st, codeptr + 2); + if (error) + return fz_rethrow(error, "runtime error in if-branch"); + } + else { + error = evalpostscriptfunc(func, st, func->u.p.code[codeptr].u.block); + if (error) + return fz_rethrow(error, "runtime error in else-branch"); } codeptr = func->u.p.code[codeptr + 1].u.block; break; case PSORETURN: - return nil; + return fz_okay; + + default: + return fz_throw("foreign operator in calculator function"); } break; default: - return fz_throw("syntaxerror: postscript calculator"); - break; + return fz_throw("foreign object in calculator function"); } } - -cleanup: - return error; } /* @@ -910,7 +934,7 @@ static int bps_supported[] = { 1, 2, 4, 8, 12, 16, 24, 32 }; static fz_error * loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int gen) { - fz_error *error = nil; + fz_error *error; fz_stream *stream; fz_obj *obj; int samplecount; @@ -923,28 +947,28 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int ge obj = fz_dictgets(dict, "Size"); if (!fz_isarray(obj) || fz_arraylen(obj) != func->m) - goto cleanup0; + return fz_throw("malformed /Size"); for (i = 0; i < func->m; ++i) func->u.sa.size[i] = fz_toint(fz_arrayget(obj, i)); obj = fz_dictgets(dict, "BitsPerSample"); if (!fz_isint(obj)) - goto cleanup0; + return fz_throw("malformed /BitsPerSample"); func->u.sa.bps = bps = fz_toint(obj); - pdf_logrsrc("bsp %d\n", bps); + pdf_logrsrc("bps %d\n", bps); for (i = 0; i < nelem(bps_supported); ++i) if (bps == bps_supported[i]) break; if (i == nelem(bps_supported)) - goto cleanup0; + return fz_throw("unsupported BitsPerSample (%d)", bps); obj = fz_dictgets(dict, "Encode"); if (fz_isarray(obj)) { if (fz_arraylen(obj) != func->m * 2) - goto cleanup0; + return fz_throw("malformed /Encode"); for (i = 0; i < func->m; ++i) { func->u.sa.encode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); @@ -964,7 +988,7 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int ge if (fz_isarray(obj)) { if (fz_arraylen(obj) != func->n * 2) - goto cleanup0; + return fz_throw("malformed /Decode"); for (i = 0; i < func->n; ++i) { func->u.sa.decode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); @@ -987,14 +1011,11 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int ge func->u.sa.samples = fz_malloc(samplecount * sizeof(int)); if (!func->u.sa.samples) - { - error = fz_outofmem; - goto cleanup0; - } + return fz_throw("outofmem: samples"); error = pdf_openstream(&stream, xref, oid, gen); if (error) - goto cleanup0; + return fz_rethrow(error, "cannot open samples stream"); /* read samples */ { @@ -1007,8 +1028,11 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int ge { if (fz_peekbyte(stream) == EOF) { - error = fz_throw("syntaxerror: too few samples in function"); - goto cleanup1; + fz_dropstream(stream); + error = fz_readerror(stream); + if (error) + return fz_rethrow(error, "truncated sample stream"); + return fz_throw("truncated sample stream"); } if (bps == 8) { @@ -1036,19 +1060,17 @@ loadsamplefunc(pdf_function *func, pdf_xref *xref, fz_obj *dict, int oid, int ge func->u.sa.samples[i] = s; } + + error = fz_readerror(stream); + if (error) + return fz_rethrow(error, "truncated sample stream"); } fz_dropstream(stream); pdf_logrsrc("}\n"); - return nil; - -cleanup1: - fz_dropstream(stream); -cleanup0: - if (error) return error; - return fz_throw("syntaxerror: sample function"); + return fz_okay; } static fz_error * @@ -1069,7 +1091,7 @@ evalsamplefunc(pdf_function *func, float *in, float *out) { x = CLAMP(in[i], func->domain[i][0], func->domain[i][1]); x = LERP(x, func->domain[i][0], func->domain[i][1], - func->u.sa.encode[i][0], func->u.sa.encode[i][1]); + func->u.sa.encode[i][0], func->u.sa.encode[i][1]); x = CLAMP(x, 0, func->u.sa.size[i] - 1); e[0][i] = floor(x); e[1][i] = ceil(x); @@ -1081,7 +1103,7 @@ evalsamplefunc(pdf_function *func, float *in, float *out) s0 = fz_malloc((1 << func->m) * 2 * sizeof(float)); s1 = s0 + (1 << func->m); if (!s0) - return fz_outofmem; + return fz_throw("outofmem: scratch buffer"); } /* FIXME i think this is wrong... test with 2 samples it gets wrong idxs */ @@ -1107,14 +1129,14 @@ evalsamplefunc(pdf_function *func, float *in, float *out) /* decode output values */ out[i] = LERP(s0[0], 0, (1 << func->u.sa.bps) - 1, - func->u.sa.decode[i][0], func->u.sa.decode[i][1]); + func->u.sa.decode[i][0], func->u.sa.decode[i][1]); out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); } if (func->m > 4) fz_free(s0); - return nil; + return fz_okay; } /* @@ -1124,18 +1146,17 @@ evalsamplefunc(pdf_function *func, float *in, float *out) static fz_error * loadexponentialfunc(pdf_function *func, fz_obj *dict) { - fz_error *error = nil; fz_obj *obj; int i; pdf_logrsrc("exponential function {\n"); if (func->m != 1) - goto cleanup; + return fz_throw("/Domain must be one dimension (%d)", func->m); obj = fz_dictgets(dict, "N"); if (!fz_isint(obj) && !fz_isreal(obj)) - goto cleanup; + return fz_throw("malformed /N"); func->u.e.n = fz_toreal(obj); pdf_logrsrc("n %g\n", func->u.e.n); @@ -1157,7 +1178,7 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) if (fz_isarray(obj)) { if (fz_arraylen(obj) != func->n) - goto cleanup; + return fz_throw("/C1 must match /C0 length"); for (i = 0; i < func->n; ++i) func->u.e.c1[i] = fz_toreal(fz_arrayget(obj, i)); pdf_logrsrc("c1 %d\n", func->n); @@ -1165,23 +1186,18 @@ loadexponentialfunc(pdf_function *func, fz_obj *dict) else { if (func->n != 1) - goto cleanup; + return fz_throw("/C1 must match /C0 length"); func->u.e.c1[0] = 1; } pdf_logrsrc("}\n"); - return nil; - -cleanup: - if (error) return error; - return fz_throw("syntaxerror: exponential function"); + return fz_okay; } static fz_error * evalexponentialfunc(pdf_function *func, float in, float *out) { - fz_error *error = nil; float x = in; float tmp; int i; @@ -1190,9 +1206,9 @@ evalexponentialfunc(pdf_function *func, float in, float *out) /* constraint */ if (func->u.e.n != (int)func->u.e.n && x < 0) - goto cleanup; + return fz_throw("constraint error"); if (func->u.e.n < 0 && x == 0) - goto cleanup; + return fz_throw("constraint error"); tmp = pow(x, func->u.e.n); for (i = 0; i < func->n; ++i) @@ -1202,11 +1218,7 @@ evalexponentialfunc(pdf_function *func, float in, float *out) out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); } - return nil; - -cleanup: - if (error) return error; - return fz_throw("rangecheck: exponential function"); + return fz_okay; } /* @@ -1217,7 +1229,7 @@ static fz_error * loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) { pdf_function **funcs = func->u.st.funcs; - fz_error *error = nil; + fz_error *error; fz_obj *obj; fz_obj *sub; fz_obj *num; @@ -1229,34 +1241,50 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) func->u.st.k = 0; if (func->m != 1) - goto cleanup; + return fz_throw("/Domain must be one dimension (%d)", func->m); obj = fz_dictgets(dict, "Functions"); { error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve /Functions"); k = fz_arraylen(obj); func->u.st.k = k; pdf_logrsrc("k %d\n", func->u.st.k); - assert(k < MAXK); + + if (k >= MAXK) + { + fz_dropobj(obj); + return fz_throw("assert: /K too big (%d)", k); + } for (i = 0; i < k; ++i) { sub = fz_arrayget(obj, i); error = pdf_loadfunction(funcs + i, xref, sub); if (error) - goto cleanup; + { + fz_dropobj(obj); + return fz_rethrow(error, "cannot load sub function %d", i); + } if (funcs[i]->m != 1 || funcs[i]->n != funcs[0]->n) - goto cleanup; + { + fz_dropobj(obj); + return fz_rethrow(error, "sub function %d /Domain or /Range mismatch", i); + } } if (!func->n) + { func->n = funcs[0]->n; + } else if (func->n != funcs[0]->n) - goto cleanup; + { + fz_dropobj(obj); + return fz_rethrow(error, "sub function /Domain or /Range mismatch"); + } fz_dropobj(obj); } @@ -1265,25 +1293,37 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) { error = pdf_resolve(&obj, xref); if (error) - goto cleanup; + return fz_rethrow(error, "cannot resolve /Bounds"); if (!fz_isarray(obj) || fz_arraylen(obj) != k - 1) - goto cleanup; + { + fz_dropobj(obj); + return fz_throw("malformed /Bounds (not array or wrong length)"); + } for (i = 0; i < k-1; ++i) { num = fz_arrayget(obj, i); if (!fz_isint(num) && !fz_isreal(num)) - goto cleanup; + { + fz_dropobj(obj); + return fz_throw("malformed /Bounds (item not number)"); + } func->u.st.bounds[i] = fz_toreal(num); if (i && func->u.st.bounds[i-1] >= func->u.st.bounds[i]) - goto cleanup; + { + fz_dropobj(obj); + return fz_throw("malformed /Bounds (item not monotonic)"); + } } if (k != 1 && - (func->domain[0][0] >= func->u.st.bounds[0] || - func->domain[0][1] <= func->u.st.bounds[k-2])) - goto cleanup; + (func->domain[0][0] >= func->u.st.bounds[0] || + func->domain[0][1] <= func->u.st.bounds[k-2])) + { + fz_dropobj(obj); + return fz_throw("malformed /Bounds (domain mismatch)"); + } fz_dropobj(obj); } @@ -1291,31 +1331,33 @@ loadstitchingfunc(pdf_function *func, pdf_xref *xref, fz_obj *dict) obj = fz_dictgets(dict, "Encode"); { error = pdf_resolve(&obj, xref); + if (error) + return fz_rethrow(error, "cannot resolve /Encode"); + if (!fz_isarray(obj) || fz_arraylen(obj) != k * 2) - goto cleanup; + { + fz_dropobj(obj); + return fz_throw("malformed /Encode"); + } + for (i = 0; i < k; ++i) { func->u.st.encode[i][0] = fz_toreal(fz_arrayget(obj, i*2+0)); func->u.st.encode[i][1] = fz_toreal(fz_arrayget(obj, i*2+1)); } + fz_dropobj(obj); } pdf_logrsrc("}\n"); - return nil; - -cleanup: - fz_dropobj(obj); - if (error) - return error; - return fz_throw("syntaxerror: stitching function"); + return fz_okay; } static fz_error* evalstitchingfunc(pdf_function *func, float in, float *out) { - fz_error *error = nil; + fz_error *error; float low, high; int k = func->u.st.k; float *bounds = func->u.st.bounds; @@ -1354,9 +1396,9 @@ evalstitchingfunc(pdf_function *func, float in, float *out) error = pdf_evalfunction(func->u.st.funcs[i], &in, 1, out, func->n); if (error) - return error; + return fz_rethrow(error, "cannot evaluate sub function %d", i); - return nil; + return fz_okay; } /* @@ -1407,15 +1449,16 @@ pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref) if ((*funcp = pdf_finditem(xref->store, PDF_KFUNCTION, ref))) { pdf_keepfunction(*funcp); - return nil; + return fz_okay; } pdf_logrsrc("load function %d %d {\n", fz_tonum(ref), fz_togen(ref)); func = fz_malloc(sizeof(pdf_function)); if (!func) - return fz_outofmem; + return fz_throw("outofmem: function struct"); + memset(func, 0, sizeof(pdf_function)); func->refs = 1; dict = ref; @@ -1423,7 +1466,7 @@ pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref) if (error) { fz_free(func); - goto cleanup; + return fz_rethrow(error, "cannot resolve function object"); } obj = fz_dictgets(dict, "FunctionType"); @@ -1460,38 +1503,59 @@ pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref) func->n = 0; } - assert(func->m < MAXM); - assert(func->n < MAXN); + if (func->m >= MAXM || func->n >= MAXN) + { + fz_free(func); + fz_dropobj(dict); + return fz_throw("assert: /Domain or /Range too big"); + } switch(func->type) { case SAMPLE: error = loadsamplefunc(func, xref, dict, fz_tonum(ref), fz_togen(ref)); if (error) - goto cleanup; + { + pdf_dropfunction(func); + fz_dropobj(dict); + return fz_rethrow(error, "cannot load sampled function (%d)", fz_tonum(ref)); + } break; case EXPONENTIAL: error = loadexponentialfunc(func, dict); if (error) - goto cleanup; + { + pdf_dropfunction(func); + fz_dropobj(dict); + return fz_rethrow(error, "cannot load exponential function (%d)", fz_tonum(ref)); + } break; case STITCHING: error = loadstitchingfunc(func, xref, dict); if (error) - goto cleanup; + { + pdf_dropfunction(func); + fz_dropobj(dict); + return fz_rethrow(error, "cannot load stitching function (%d)", fz_tonum(ref)); + } break; case POSTSCRIPT: error = loadpostscriptfunc(func, xref, dict, fz_tonum(ref), fz_togen(ref)); if (error) - goto cleanup; + { + pdf_dropfunction(func); + fz_dropobj(dict); + return fz_rethrow(error, "cannot load calculator function (%d)", fz_tonum(ref)); + } break; default: - error = fz_throw("syntaxerror: unknown function type"); - goto cleanup; + fz_free(func); + fz_dropobj(dict); + return fz_throw("unknown function type %d (function %d)", func->type, fz_tonum(ref)); } fz_dropobj(dict); @@ -1500,34 +1564,44 @@ pdf_loadfunction(pdf_function **funcp, pdf_xref *xref, fz_obj *ref) error = pdf_storeitem(xref->store, PDF_KFUNCTION, ref, func); if (error) - goto cleanup; + { + pdf_dropfunction(func); + fz_dropobj(dict); + return fz_rethrow(error, "cannot store function resource"); + } *funcp = func; - return nil; - -cleanup: - fz_dropobj(dict); - pdf_dropfunction(func); - return error; + return fz_okay; } fz_error * pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen) { - fz_error *error = nil; + fz_error *error; int i; if (func->m != inlen || func->n != outlen) - return fz_throw("rangecheck: function argument count mismatch"); + return fz_throw("function argument count mismatch"); switch(func->type) { case SAMPLE: - return evalsamplefunc(func, in, out); + error = evalsamplefunc(func, in, out); + if (error) + return fz_rethrow(error, "cannot evaluate sampled function"); + break; + case EXPONENTIAL: - return evalexponentialfunc(func, *in, out); + error = evalexponentialfunc(func, *in, out); + if (error) + return fz_rethrow(error, "cannot evaluate exponential function"); + break; + case STITCHING: - return evalstitchingfunc(func, *in, out); + error = evalstitchingfunc(func, *in, out); + if (error) + return fz_rethrow(error, "cannot evaluate stitching function"); + break; case POSTSCRIPT: { @@ -1539,7 +1613,7 @@ pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outle error = evalpostscriptfunc(func, &st, 0); if (error) - return error; + return fz_rethrow(error, "cannot evaluate calculator function"); for (i = func->n - 1; i >= 0; --i) { @@ -1547,10 +1621,12 @@ pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outle out[i] = CLAMP(out[i], func->range[i][0], func->range[i][1]); } } - return nil; + break; + + default: + return fz_throw("assert: unknown function type"); } -cleanup: - return error; + return fz_okay; } diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c index b6d7327a..27cc7680 100644 --- a/mupdf/pdf_image.c +++ b/mupdf/pdf_image.c @@ -28,7 +28,7 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, img = fz_malloc(sizeof(pdf_image)); if (!img) - return fz_outofmem; + return fz_throw("outofmem: image struct"); pdf_logimage("load inline image %p {\n", img); @@ -132,30 +132,26 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, if (error) return error; - if (filter == nil) - goto thereisnofilter; - error = fz_openrfilter(&tempfile, filter, file); if (error) return error; - i = fz_readall(&img->samples, tempfile); - if (i < 0) - return fz_ioerror(tempfile); + error = fz_readall(&img->samples, tempfile); + if (error) + return error; fz_dropfilter(filter); fz_dropstream(tempfile); } else { -thereisnofilter: error = fz_newbuffer(&img->samples, img->super.h * img->stride); if (error) return error; - i = fz_read(file, img->samples->bp, img->super.h * img->stride); - if (i < 0) - return fz_ioerror(file); + error = fz_read(&i, file, img->samples->bp, img->super.h * img->stride); + if (error) + return error; img->samples->wp += img->super.h * img->stride; } @@ -225,7 +221,7 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) img = fz_malloc(sizeof(pdf_image)); if (!img) - return fz_outofmem; + return fz_throw("outofmem: image struct"); pdf_logimage("load image %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), img); diff --git a/mupdf/pdf_interpret.c b/mupdf/pdf_interpret.c index a458750b..0404a292 100644 --- a/mupdf/pdf_interpret.c +++ b/mupdf/pdf_interpret.c @@ -8,9 +8,9 @@ pdf_newcsi(pdf_csi **csip, int maskonly) pdf_csi *csi; fz_node *node; - csi = *csip = fz_malloc(sizeof(pdf_csi)); + csi = fz_malloc(sizeof(pdf_csi)); if (!csi) - return fz_outofmem; + return fz_throw("outofmem: interpreter struct"); pdf_initgstate(&csi->gstate[0]); @@ -22,14 +22,14 @@ pdf_newcsi(pdf_csi **csip, int maskonly) error = fz_newpathnode(&csi->path); if (error) { fz_free(csi); - return error; + return fz_rethrow(error, "cannot create path node"); } error = fz_newtree(&csi->tree); if (error) { fz_dropnode((fz_node*)csi->path); fz_free(csi); - return error; + return fz_rethrow(error, "cannot create tree"); } error = fz_newovernode(&node); @@ -50,7 +50,8 @@ pdf_newcsi(pdf_csi **csip, int maskonly) csi->tm = fz_identity(); csi->tlm = fz_identity(); - return nil; + *csip = csi; + return fz_okay; } static void @@ -107,7 +108,7 @@ gsave(pdf_csi *csi) pdf_keepmaterial(&gs->stroke); pdf_keepmaterial(&gs->fill); - return nil; + return fz_okay; } static fz_error * @@ -123,14 +124,14 @@ grestore(pdf_csi *csi) csi->gtop --; - return nil; + return fz_okay; } void pdf_dropcsi(pdf_csi *csi) { while (csi->gtop) - grestore(csi); + grestore(csi); /* no need to check for impossible errors */ if (csi->gstate[csi->gtop].fill.cs) fz_dropcolorspace(csi->gstate[csi->gtop].fill.cs); @@ -176,13 +177,13 @@ runxobject(pdf_csi *csi, pdf_xref *xref, pdf_xobject *xobj) error = fz_newtransformnode(&transform, xobj->matrix); if (error) - return error; + return fz_rethrow(error, "cannot create transform node"); error = pdf_addtransform(csi->gstate + csi->gtop, transform); if (error) { fz_dropnode(transform); - return error; + return fz_rethrow(error, "cannot add transform node"); } /* run contents */ @@ -191,21 +192,21 @@ runxobject(pdf_csi *csi, pdf_xref *xref, pdf_xobject *xobj) error = fz_openrbuffer(&file, xobj->contents); if (error) - return error; + return fz_rethrow(error, "cannot open XObject stream"); error = pdf_runcsi(csi, xref, xobj->resources, file); fz_dropstream(file); if (error) - return error; + return fz_rethrow(error, "cannot interpret XObject stream"); /* grestore */ error = grestore(csi); if (error) - return error; + return fz_rethrow(error, "cannot grestore"); - return nil; + return fz_okay; } /* @@ -217,26 +218,36 @@ runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, fz_ob { fz_error *error; pdf_image *img; - unsigned char buf[256]; + char buf[256]; int token; int len; error = pdf_loadinlineimage(&img, xref, rdb, dict, file); if (error) - return error; + return fz_rethrow(error, "cannot load inline image"); - token = pdf_lex(file, buf, sizeof buf, &len); - if (token != PDF_TKEYWORD || memcmp("EI", buf, 2)) - fz_warn("syntaxerror: corrupt inline image"); + error = pdf_lex(&token, file, buf, sizeof buf, &len); + if (error) + { + fz_dropimage((fz_image*)img); + return fz_rethrow(error, "syntax error after inline image"); + } + + if (token != PDF_TKEYWORD || strcmp("EI", buf)) + { + fz_dropimage((fz_image*)img); + return fz_throw("syntax error after inline image"); + } error = pdf_showimage(csi, img); if (error) { fz_dropimage((fz_image*)img); - return error; + return fz_rethrow(error, "cannot draw image"); } - return nil; + fz_dropimage((fz_image*)img); + return fz_okay; } /* @@ -260,11 +271,11 @@ runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate) { gstate->font = pdf_finditem(xref->store, PDF_KFONT, fz_arrayget(val, 0)); if (!gstate->font) - return fz_throw("syntaxerror: missing font resource"); + return fz_throw("cannot find font in store"); gstate->size = fz_toreal(fz_arrayget(val, 1)); } else - return fz_throw("syntaxerror in ExtGState/Font"); + return fz_throw("malformed /Font"); } else if (!strcmp(s, "LW")) @@ -287,7 +298,7 @@ runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate) gstate->dashphase = fz_toreal(fz_arrayget(val, 1)); } else - return fz_throw("syntaxerror in ExtGState/D"); + return fz_throw("malformed /D"); } else if (!strcmp(s, "CA")) @@ -296,7 +307,7 @@ runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate) gstate->fill.alpha = fz_toreal(val); } - return nil; + return fz_okay; } /* @@ -377,9 +388,12 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) m.f = fz_toreal(csi->stack[5]); error = fz_newtransformnode(&transform, m); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot concatenate matrix"); + error = pdf_addtransform(gstate, transform); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot concatenate matrix"); } else if (!strcmp(buf, "ri")) @@ -398,33 +412,37 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) dict = fz_dictgets(rdb, "ExtGState"); if (!dict) - return fz_throw("syntaxerror: missing extgstate resource"); + return fz_throw("cannot find ExtGState dictionary"); obj = fz_dictget(dict, csi->stack[0]); if (!obj) - return fz_throw("syntaxerror: missing extgstate resource"); + return fz_throw("cannot find extgstate resource /%s", fz_toname(csi->stack[0])); - runextgstate(gstate, xref, obj); + error = runextgstate(gstate, xref, obj); + if (error) + return fz_rethrow(error, "cannot set ExtGState"); } else if (!strcmp(buf, "re")) { if (csi->top != 4) goto syntaxerror; + x = fz_toreal(csi->stack[0]); y = fz_toreal(csi->stack[1]); w = fz_toreal(csi->stack[2]); h = fz_toreal(csi->stack[3]); + error = fz_moveto(csi->path, x, y); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw rectangle"); error = fz_lineto(csi->path, x + w, y); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw rectangle"); error = fz_lineto(csi->path, x + w, y + h); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw rectangle"); error = fz_lineto(csi->path, x, y + h); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw rectangle"); error = fz_closepath(csi->path); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw rectangle"); } else if (!strcmp(buf, "f*")) @@ -432,7 +450,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 1, 0, 1); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); } else if (!strcmp(buf, "B*")) @@ -440,7 +458,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 1, 1, 1); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); } else if (!strcmp(buf, "b*")) @@ -448,7 +466,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 1, 1, 1, 1); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); } else if (!strcmp(buf, "W*")) @@ -480,10 +498,10 @@ Lsetcolorspace: if (!strcmp(fz_toname(obj), "Pattern")) { error = pdf_setpattern(csi, what, nil, nil); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set pattern"); } - else + else { if (!strcmp(fz_toname(obj), "DeviceGray")) cs = pdf_devicegray; @@ -495,18 +513,18 @@ Lsetcolorspace: { fz_obj *dict = fz_dictgets(rdb, "ColorSpace"); if (!dict) - return fz_throw("syntaxerror: missing colorspace resource"); + return fz_throw("cannot find ColorSpace dictionary"); obj = fz_dictget(dict, obj); if (!obj) - return fz_throw("syntaxerror: missing colorspace resource"); + return fz_throw("cannot find colorspace resource /%s", fz_toname(csi->stack[0])); cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj); if (!cs) - return fz_throw("syntaxerror: missing colorspace resource"); + return fz_throw("cannot find colorspace in store"); } error = pdf_setcolorspace(csi, what, cs); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set colorspace"); } } @@ -537,14 +555,14 @@ Lsetcolor: switch (kind) { case PDF_MNONE: - return fz_throw("syntaxerror: cannot set color in mask objects"); + return fz_throw("cannot set color in mask objects"); case PDF_MINDEXED: if (csi->top != 1) goto syntaxerror; v[0] = fz_toreal(csi->stack[0]); error = pdf_setcolor(csi, what, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set indexed color"); break; case PDF_MCOLOR: @@ -554,7 +572,7 @@ Lsetcolor: for (i = 0; i < csi->top; i++) v[i] = fz_toreal(csi->stack[i]); error = pdf_setcolor(csi, what, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set color"); break; case PDF_MPATTERN: @@ -563,33 +581,34 @@ Lsetcolor: dict = fz_dictgets(rdb, "Pattern"); if (!dict) - return fz_throw("syntaxerror: missing pattern resource"); + return fz_throw("cannot find Pattern dictionary"); obj = fz_dictget(dict, csi->stack[csi->top - 1]); if (!obj) - return fz_throw("syntaxerror: missing pattern resource"); + return fz_throw("cannot find pattern resource /%s", + fz_toname(csi->stack[csi->top - 1])); pat = pdf_finditem(xref->store, PDF_KPATTERN, obj); if (pat) { error = pdf_setpattern(csi, what, pat, csi->top == 1 ? nil : v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set pattern"); } shd = pdf_finditem(xref->store, PDF_KSHADE, obj); if (shd) { error = pdf_setshade(csi, what, shd); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set shade"); } if (!pat && !shd) - return fz_throw("syntaxerror: missing pattern resource"); + return fz_throw("cannot find pattern or shade in store"); break; case PDF_MSHADE: - return fz_throw("syntaxerror: cannot set color in shade objects"); + return fz_throw("cannot set color in shade objects"); } } @@ -603,9 +622,9 @@ Lsetcolor: v[2] = fz_toreal(csi->stack[2]); error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicergb); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set rgb colorspace"); error = pdf_setcolor(csi, PDF_MFILL, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set rgb color"); } else if (!strcmp(buf, "RG")) @@ -618,9 +637,9 @@ Lsetcolor: v[2] = fz_toreal(csi->stack[2]); error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicergb); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set rgb colorspace"); error = pdf_setcolor(csi, PDF_MSTROKE, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set rgb color"); } else if (!strcmp(buf, "BT")) @@ -638,12 +657,12 @@ Lsetcolor: error = pdf_flushtext(csi); if (error) - return error; + return fz_rethrow(error, "cannot finish text object (ET)"); if (csi->textclip) { error = pdf_addclipmask(gstate, csi->textclip); - if (error) return error; + if (error) return fz_rethrow(error, "cannot add text clip mask"); csi->textclip = nil; } } @@ -668,7 +687,8 @@ Lsetcolor: goto syntaxerror; error = pdf_flushtext(csi); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot finish text object (state change)"); gstate->scale = fz_toreal(csi->stack[0]) / 100.0; } @@ -690,15 +710,15 @@ Lsetcolor: dict = fz_dictgets(rdb, "Font"); if (!dict) - return fz_throw("syntaxerror: missing font resource"); + return fz_throw("cannot find Font dictionary"); obj = fz_dictget(dict, csi->stack[0]); if (!obj) - return fz_throw("syntaxerror: missing font resource"); + return fz_throw("cannot find font resource: %s", fz_toname(csi->stack[0])); gstate->font = pdf_finditem(xref->store, PDF_KFONT, obj); if (!gstate->font) - return fz_throw("syntaxerror: missing font resource"); + return fz_throw("cannot find font in store"); gstate->size = fz_toreal(csi->stack[1]); } @@ -742,7 +762,8 @@ Lsetcolor: goto syntaxerror; error = pdf_flushtext(csi); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot finish text object (state change)"); csi->tm.a = fz_toreal(csi->stack[0]); csi->tm.b = fz_toreal(csi->stack[1]); @@ -767,7 +788,7 @@ Lsetcolor: if (csi->top != 1) goto syntaxerror; error = pdf_showtext(csi, csi->stack[0]); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw text"); } else if (!strcmp(buf, "TJ")) @@ -775,7 +796,7 @@ Lsetcolor: if (csi->top != 1) goto syntaxerror; error = pdf_showtext(csi, csi->stack[0]); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw text"); } else if (!strcmp(buf, "Do")) @@ -790,26 +811,23 @@ Lsetcolor: dict = fz_dictgets(rdb, "XObject"); if (!dict) -{ -fz_debugobj(rdb); - return fz_throw("syntaxerror: missing xobject resource"); -} + return fz_throw("cannot find XObject dictionary"); obj = fz_dictget(dict, csi->stack[0]); if (!obj) - return fz_throw("syntaxerror: missing xobject resource"); + return fz_throw("cannot find xobject resource: %s", fz_toname(csi->stack[0])); img = pdf_finditem(xref->store, PDF_KIMAGE, obj); xobj = pdf_finditem(xref->store, PDF_KXOBJECT, obj); if (!img && !xobj) - return fz_throw("syntaxerror: missing xobject resource"); + return fz_throw("cannot find image or xobject in store"); if (img) { error = pdf_showimage(csi, img); if (error) - return error; + return fz_rethrow(error, "cannot draw image"); } if (xobj) @@ -817,7 +835,7 @@ fz_debugobj(rdb); clearstack(csi); error = runxobject(csi, xref, xobj); if (error) - return error; + return fz_rethrow(error, "cannot draw xobject"); } } @@ -832,18 +850,18 @@ fz_debugobj(rdb); dict = fz_dictgets(rdb, "Shading"); if (!dict) - return fz_throw("syntaxerror: missing shading resource"); + return fz_throw("cannot find Shading dictionary"); obj = fz_dictget(dict, csi->stack[csi->top - 1]); if (!obj) - return fz_throw("syntaxerror: missing shading resource"); + return fz_throw("cannot find shade resource: %s", fz_toname(csi->stack[csi->top - 1])); shd = pdf_finditem(xref->store, PDF_KSHADE, obj); if (!shd) - return fz_throw("syntaxerror: missing shading resource"); + return fz_throw("cannot find shade in store"); error = pdf_addshade(gstate, shd); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw shade"); } else if (!strcmp(buf, "d0")) @@ -856,7 +874,11 @@ fz_debugobj(rdb); } else - if (!csi->xbalance) goto syntaxerror; + { + /* don't fail on unknown keywords if braced by BX/EX */ + if (!csi->xbalance) + goto syntaxerror; + } } else switch (buf[0]) @@ -867,7 +889,7 @@ fz_debugobj(rdb); goto syntaxerror; error = gsave(csi); if (error) - return error; + return fz_rethrow(error, "cannot gsave"); break; case 'Q': @@ -875,7 +897,7 @@ fz_debugobj(rdb); goto syntaxerror; error = grestore(csi); if (error) - return error; + return fz_rethrow(error, "cannot grestore"); break; case 'w': @@ -910,7 +932,7 @@ fz_debugobj(rdb); fz_obj *array = csi->stack[0]; gstate->dashlen = fz_arraylen(array); if (gstate->dashlen > 32) - return fz_throw("rangecheck: too large dash pattern"); + return fz_throw("assert: dash pattern too big"); for (i = 0; i < gstate->dashlen; i++) gstate->dashlist[i] = fz_toreal(fz_arrayget(array, i)); gstate->dashphase = fz_toreal(csi->stack[1]); @@ -928,14 +950,18 @@ fz_debugobj(rdb); goto syntaxerror; a = fz_toreal(csi->stack[0]); b = fz_toreal(csi->stack[1]); - return fz_moveto(csi->path, a, b); + error = fz_moveto(csi->path, a, b); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'l': if (csi->top != 2) goto syntaxerror; a = fz_toreal(csi->stack[0]); b = fz_toreal(csi->stack[1]); - return fz_lineto(csi->path, a, b); + error = fz_lineto(csi->path, a, b); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'c': if (csi->top != 6) @@ -946,7 +972,9 @@ fz_debugobj(rdb); d = fz_toreal(csi->stack[3]); e = fz_toreal(csi->stack[4]); f = fz_toreal(csi->stack[5]); - return fz_curveto(csi->path, a, b, c, d, e, f); + error = fz_curveto(csi->path, a, b, c, d, e, f); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'v': if (csi->top != 4) @@ -955,7 +983,9 @@ fz_debugobj(rdb); b = fz_toreal(csi->stack[1]); c = fz_toreal(csi->stack[2]); d = fz_toreal(csi->stack[3]); - return fz_curvetov(csi->path, a, b, c, d); + error = fz_curvetov(csi->path, a, b, c, d); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'y': if (csi->top != 4) @@ -964,25 +994,29 @@ fz_debugobj(rdb); b = fz_toreal(csi->stack[1]); c = fz_toreal(csi->stack[2]); d = fz_toreal(csi->stack[3]); - return fz_curvetoy(csi->path, a, b, c, d); + error = fz_curvetoy(csi->path, a, b, c, d); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'h': if (csi->top != 0) goto syntaxerror; - return fz_closepath(csi->path); + error = fz_closepath(csi->path); + if (error) return fz_rethrow(error, "cannot create path node"); + break; case 'S': if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 0, 1, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 's': if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 1, 0, 1, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 'F': @@ -990,28 +1024,28 @@ fz_debugobj(rdb); if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 1, 0, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 'B': if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 1, 1, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 'b': if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 1, 1, 1, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 'n': if (csi->top != 0) goto syntaxerror; error = pdf_showpath(csi, 0, 0, 0, 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw path"); break; case 'W': @@ -1020,15 +1054,15 @@ fz_debugobj(rdb); csi->clip = 1; break; - case 'g': + case 'g': if (csi->top != 1) goto syntaxerror; v[0] = fz_toreal(csi->stack[0]); error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicegray); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set gray colorspace"); error = pdf_setcolor(csi, PDF_MFILL, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set gray color"); break; case 'G': @@ -1037,9 +1071,9 @@ fz_debugobj(rdb); v[0] = fz_toreal(csi->stack[0]); error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicegray); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set gray colorspace"); error = pdf_setcolor(csi, PDF_MSTROKE, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set gray color"); break; case 'k': @@ -1052,9 +1086,9 @@ fz_debugobj(rdb); v[3] = fz_toreal(csi->stack[3]); error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicecmyk); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set cmyk colorspace"); error = pdf_setcolor(csi, PDF_MFILL, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set cmyk color"); break; case 'K': @@ -1067,9 +1101,9 @@ fz_debugobj(rdb); v[3] = fz_toreal(csi->stack[3]); error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicecmyk); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set cmyk colorspace"); error = pdf_setcolor(csi, PDF_MSTROKE, v); - if (error) return error; + if (error) return fz_rethrow(error, "cannot set cmyk color"); break; case '\'': @@ -1081,7 +1115,7 @@ fz_debugobj(rdb); csi->tm = csi->tlm; error = pdf_showtext(csi, csi->stack[0]); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw text"); break; case '"': @@ -1096,33 +1130,37 @@ fz_debugobj(rdb); csi->tm = csi->tlm; error = pdf_showtext(csi, csi->stack[2]); - if (error) return error; + if (error) return fz_rethrow(error, "cannot draw text"); break; default: - if (!csi->xbalance) goto syntaxerror; + /* don't fail on unknown keywords if braced by BX/EX */ + if (!csi->xbalance) + goto syntaxerror; } - return nil; + return fz_okay; syntaxerror: - return fz_throw("syntaxerror in content stream: '%s'", buf); + return fz_throw("syntaxerror near '%s'", buf); } fz_error * pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file) { fz_error *error; - unsigned char buf[65536]; + char buf[65536]; int token, len; fz_obj *obj; while (1) { if (csi->top == 31) - return fz_throw("stack overflow in content stream"); + return fz_throw("stack overflow"); - token = pdf_lex(file, buf, sizeof buf, &len); + error = pdf_lex(&token, file, buf, sizeof buf, &len); + if (error) + return fz_rethrow(error, "lexical error in content stream"); if (csi->array) { @@ -1134,111 +1172,115 @@ pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file) } else if (token == PDF_TINT || token == PDF_TREAL) { - error = fz_newreal(&obj, atof((char *) buf)); - if (error) return error; + error = fz_newreal(&obj, atof(buf)); + if (error) return fz_rethrow(error, "cannot create number"); error = fz_arraypush(csi->array, obj); fz_dropobj(obj); - if (error) return error; + if (error) return fz_rethrow(error, "cannot add number to array"); } else if (token == PDF_TSTRING) { - error = fz_newstring(&obj, (char *) buf, len); - if (error) return error; + error = fz_newstring(&obj, buf, len); + if (error) return fz_rethrow(error, "cannot create string"); error = fz_arraypush(csi->array, obj); fz_dropobj(obj); - if (error) return error; + if (error) return fz_rethrow(error, "cannot add string to array"); } else if (token == PDF_TEOF) { - return nil; + return fz_okay; } else { clearstack(csi); - return fz_throw("syntaxerror in content stream"); + return fz_throw("syntaxerror in array"); } } else switch (token) { case PDF_TEOF: - return nil; + return fz_okay; - /* optimize text-object array parsing */ + /* optimize text-object array parsing */ case PDF_TOARRAY: error = fz_newarray(&csi->array, 8); - if (error) return error; + if (error) return fz_rethrow(error, "cannot create array"); break; case PDF_TODICT: - error = pdf_parsedict(&csi->stack[csi->top], file, (char *) buf, sizeof buf); - if (error) return error; + error = pdf_parsedict(&csi->stack[csi->top], file, buf, sizeof buf); + if (error) return fz_rethrow(error, "cannot parse dictionary"); csi->top ++; break; case PDF_TNAME: - error = fz_newname(&csi->stack[csi->top], (char *) buf); - if (error) return error; + error = fz_newname(&csi->stack[csi->top], buf); + if (error) return fz_rethrow(error, "cannot create name"); csi->top ++; break; case PDF_TINT: - error = fz_newint(&csi->stack[csi->top], atoi((char *) buf)); - if (error) return error; + error = fz_newint(&csi->stack[csi->top], atoi(buf)); + if (error) return fz_rethrow(error, "cannot create integer"); csi->top ++; break; case PDF_TREAL: - error = fz_newreal(&csi->stack[csi->top], atof((char *) buf)); - if (error) return error; + error = fz_newreal(&csi->stack[csi->top], atof(buf)); + if (error) return fz_rethrow(error, "cannot create real"); csi->top ++; break; case PDF_TSTRING: - error = fz_newstring(&csi->stack[csi->top], (char *) buf, len); - if (error) return error; + error = fz_newstring(&csi->stack[csi->top], buf, len); + if (error) return fz_rethrow(error, "cannot create string"); csi->top ++; break; case PDF_TTRUE: error = fz_newbool(&csi->stack[csi->top], 1); - if (error) return error; + if (error) return fz_rethrow(error, "cannot create true"); csi->top ++; break; case PDF_TFALSE: error = fz_newbool(&csi->stack[csi->top], 0); - if (error) return error; + if (error) return fz_rethrow(error, "cannot create false"); csi->top ++; break; case PDF_TNULL: error = fz_newnull(&csi->stack[csi->top]); - if (error) return error; + if (error) return fz_rethrow(error, "cannot create null"); csi->top ++; break; case PDF_TKEYWORD: - if (!strcmp((char *) buf, "BI")) + if (!strcmp(buf, "BI")) { fz_obj *obj; - error = pdf_parsedict(&obj, file, (char *) buf, sizeof buf); + error = pdf_parsedict(&obj, file, buf, sizeof buf); if (error) - return error; + return fz_rethrow(error, "cannot parse inline image dictionary"); /* read whitespace after ID keyword */ fz_readbyte(file); + error = fz_readerror(file); + if (error) + return fz_rethrow(error, "cannot parse whitespace before inline image"); error = runinlineimage(csi, xref, rdb, file, obj); fz_dropobj(obj); if (error) - return error; + return fz_rethrow(error, "cannot parse inline image"); } else { - error = runkeyword(csi, xref, rdb, (char *) buf); - if (error) return error; + error = runkeyword(csi, xref, rdb, buf); + if (error) + return fz_rethrow(error, "cannot run '%s'", buf); clearstack(csi); } break; diff --git a/mupdf/pdf_lex.c b/mupdf/pdf_lex.c index 70fafd98..3af88497 100644 --- a/mupdf/pdf_lex.c +++ b/mupdf/pdf_lex.c @@ -1,24 +1,31 @@ #include <fitz.h> #include <mupdf.h> +/* + * pdf_lex will use fz_peekbyte and fz_readbyte. + * have to check for file errors with fz_readerror() after lexing. + */ + static inline int iswhite(int ch) { - return ch == '\000' || - ch == '\011' || - ch == '\012' || - ch == '\014' || - ch == '\015' || - ch == '\040'; + return + ch == '\000' || + ch == '\011' || + ch == '\012' || + ch == '\014' || + ch == '\015' || + ch == '\040'; } static inline int isdelim(int ch) { - return ch == '(' || ch == ')' || - ch == '<' || ch == '>' || - ch == '[' || ch == ']' || - ch == '{' || ch == '}' || - ch == '/' || - ch == '%'; + return + ch == '(' || ch == ')' || + ch == '<' || ch == '>' || + ch == '[' || ch == ']' || + ch == '{' || ch == '}' || + ch == '/' || + ch == '%'; } static inline int isregular(int ch) @@ -28,14 +35,15 @@ static inline int isregular(int ch) static inline int isnumber(int ch) { - return ch == '+' || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9'); + return ch == '+' || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9'); } static inline int ishex(int ch) { - return (ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f'); + return + (ch >= '0' && ch <= '9') || + (ch >= 'A' && ch <= 'F') || + (ch >= 'a' && ch <= 'f'); } static inline int fromhex(int ch) @@ -244,9 +252,10 @@ tokenfromkeyword(char *key) return PDF_TKEYWORD; } -int -pdf_lex(fz_stream *f, unsigned char *buf, int n, int *sl) +fz_error * +pdf_lex(int *ret, fz_stream *f, unsigned char *buf, int n, int *sl) { + fz_error *error; int c; while (1) @@ -254,7 +263,10 @@ pdf_lex(fz_stream *f, unsigned char *buf, int n, int *sl) c = fz_peekbyte(f); if (c == EOF) - return PDF_TEOF; + { + *ret = PDF_TEOF; + goto cleanupokay; + } else if (iswhite(c)) lexwhite(f); @@ -262,20 +274,21 @@ pdf_lex(fz_stream *f, unsigned char *buf, int n, int *sl) else if (c == '%') lexcomment(f); - else if (c == '/') { fz_readbyte(f); lexname(f, buf, n); - *sl = strlen((char *) buf); - return PDF_TNAME; + *sl = strlen(buf); + *ret = PDF_TNAME; + goto cleanupokay; } else if (c == '(') { fz_readbyte(f); *sl = lexstring(f, buf, n); - return PDF_TSTRING; + *ret = PDF_TSTRING; + goto cleanupokay; } else if (c == '<') @@ -285,12 +298,14 @@ pdf_lex(fz_stream *f, unsigned char *buf, int n, int *sl) if (c == '<') { fz_readbyte(f); - return PDF_TODICT; + *ret = PDF_TODICT; + goto cleanupokay; } else { *sl = lexhexstring(f, buf, n); - return PDF_TSTRING; + *ret = PDF_TSTRING; + goto cleanupokay; } } @@ -299,52 +314,87 @@ pdf_lex(fz_stream *f, unsigned char *buf, int n, int *sl) fz_readbyte(f); c = fz_readbyte(f); if (c == '>') - return PDF_TCDICT; - return PDF_TERROR; + { + *ret = PDF_TCDICT; + goto cleanupokay; + } + *ret = PDF_TERROR; + goto cleanuperror; } else if (c == '[') { fz_readbyte(f); - return PDF_TOARRAY; + *ret = PDF_TOARRAY; + goto cleanupokay; } else if (c == ']') { fz_readbyte(f); - return PDF_TCARRAY; + *ret = PDF_TCARRAY; + goto cleanupokay; } else if (c == '{') { fz_readbyte(f); - return PDF_TOBRACE; + *ret = PDF_TOBRACE; + goto cleanupokay; } else if (c == '}') { fz_readbyte(f); - return PDF_TCBRACE; + *ret = PDF_TCBRACE; + goto cleanupokay; } else if (isnumber(c)) { lexnumber(f, buf, n); - *sl = strlen((char *) buf); - if (strchr((char *) buf, '.')) - return PDF_TREAL; - return PDF_TINT; + *sl = strlen(buf); + if (strchr(buf, '.')) + { + *ret = PDF_TREAL; + goto cleanupokay; + } + *ret = PDF_TINT; + goto cleanupokay; } else if (isregular(c)) { lexname(f, buf, n); - *sl = strlen((char *) buf); - return tokenfromkeyword((char *) buf); + *sl = strlen(buf); + *ret = tokenfromkeyword(buf); + goto cleanupokay; } else - return PDF_TERROR; + { + *ret = PDF_TERROR; + goto cleanuperror; + } + } + +cleanupokay: + error = fz_readerror(f); + if (error) + { + *ret = PDF_TERROR; + return fz_rethrow(error, "cannot read token"); + } + return fz_okay; + +cleanuperror: + error = fz_readerror(f); + if (error) + { + *ret = PDF_TERROR; + return fz_rethrow(error, "cannot read token"); } + *ret = PDF_TERROR; + return fz_throw("lexical error"); } diff --git a/mupdf/pdf_open.c b/mupdf/pdf_open.c index d67fd82c..e9facef4 100644 --- a/mupdf/pdf_open.c +++ b/mupdf/pdf_open.c @@ -1,10 +1,11 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" static inline int iswhite(int ch) { - return ch == '\000' || ch == '\011' || ch == '\012' || - ch == '\014' || ch == '\015' || ch == '\040'; + return + ch == '\000' || ch == '\011' || ch == '\012' || + ch == '\014' || ch == '\015' || ch == '\040'; } /* @@ -14,42 +15,46 @@ static inline int iswhite(int ch) static fz_error * loadversion(pdf_xref *xref) { + fz_error *error; char buf[20]; - int n; - n = fz_seek(xref->file, 0, 0); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, 0, 0); + if (error) + return fz_rethrow(error, "cannot seek to beginning of file"); - fz_readline(xref->file, buf, sizeof buf); + error = fz_readline(xref->file, buf, sizeof buf); + if (error) + return fz_rethrow(error, "cannot read version marker"); if (memcmp(buf, "%PDF-", 5) != 0) - return fz_throw("syntaxerror: corrupt version marker"); + return fz_throw("cannot recognize version marker"); - xref->version = atof(buf + 5); + xref->version = (int) atof(buf + 5) * 10.0 + 0.5; - pdf_logxref("version %g\n", xref->version); + pdf_logxref("version %d.%d\n", xref->version / 10, xref->version % 10); - return nil; + return fz_okay; } static fz_error * readstartxref(pdf_xref *xref) { + fz_error *error; char buf[1024]; int t, n; int i; - t = fz_seek(xref->file, 0, 2); - if (t == -1) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, 0, 2); + if (error) + return fz_rethrow(error, "cannot seek to end of file"); - t = fz_seek(xref->file, MAX(0, t - ((int)sizeof buf)), 0); - if (t == -1) - return fz_ioerror(xref->file); + t = MAX(0, fz_tell(xref->file) - ((int)sizeof buf)); + error = fz_seek(xref->file, t, 0); + if (error) + return fz_rethrow(error, "cannot seek to offset %d", t); - n = fz_read(xref->file, (unsigned char *) buf, sizeof buf); - if (n == -1) - return fz_ioerror(xref->file); + error = fz_read(&n, xref->file, buf, sizeof buf); + if (error) + return fz_rethrow(error, "cannot read from file"); for (i = n - 9; i >= 0; i--) { @@ -59,11 +64,11 @@ readstartxref(pdf_xref *xref) while (iswhite(buf[i]) && i < n) i ++; xref->startxref = atoi(buf + i); - return nil; + return fz_okay; } } - return fz_throw("syntaxerror: could not find startxref"); + return fz_throw("cannot find startxref"); } /* @@ -73,6 +78,7 @@ readstartxref(pdf_xref *xref) static fz_error * readoldtrailer(pdf_xref *xref, char *buf, int cap) { + fz_error *error; int ofs, len; char *s; int n; @@ -81,9 +87,11 @@ readoldtrailer(pdf_xref *xref, char *buf, int cap) pdf_logxref("load old xref format trailer\n"); - fz_readline(xref->file, buf, cap); + error = fz_readline(xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref marker"); if (strcmp(buf, "xref") != 0) - return fz_throw("ioerror: missing xref"); + return fz_throw("cannot find xref marker"); while (1) { @@ -91,9 +99,9 @@ readoldtrailer(pdf_xref *xref, char *buf, int cap) if (!(c >= '0' && c <= '9')) break; - n = fz_readline(xref->file, buf, cap); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_readline(xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref count"); s = buf; ofs = atoi(strsep(&s, " ")); @@ -101,52 +109,89 @@ readoldtrailer(pdf_xref *xref, char *buf, int cap) /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') - fz_seek(xref->file, -(n + buf - s + 2), 1); + { + error = fz_seek(xref->file, -(n + buf - s + 2), 1); + if (error) + return fz_rethrow(error, "cannot seek in file"); + } t = fz_tell(xref->file); if (t < 0) - return fz_ioerror(xref->file); + return fz_throw("cannot tell in file"); - n = fz_seek(xref->file, t + 20 * len, 0); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, t + 20 * len, 0); + if (error) + return fz_rethrow(error, "cannot seek in file"); } - t = pdf_lex(xref->file, (unsigned char *) buf, cap, &n); + error = fz_readerror(xref->file); + if (error) + return fz_rethrow(error, "cannot read from file"); + + error = pdf_lex(&t, xref->file, buf, cap, &n); + if (error) + return fz_rethrow(error, "cannot parse trailer"); if (t != PDF_TTRAILER) - return fz_throw("syntaxerror: expected trailer"); + return fz_throw("expected trailer marker"); - t = pdf_lex(xref->file, (unsigned char *) buf, cap, &n); + error = pdf_lex(&t, xref->file, buf, cap, &n); + if (error) + return fz_rethrow(error, "cannot parse trailer"); if (t != PDF_TODICT) - return fz_throw("syntaxerror: expected trailer dictionary"); + return fz_throw("expected trailer dictionary"); - return pdf_parsedict(&xref->trailer, xref->file, buf, cap); + error = pdf_parsedict(&xref->trailer, xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot parse trailer"); + return fz_okay; } static fz_error * readnewtrailer(pdf_xref *xref, char *buf, int cap) { + fz_error *error; + pdf_logxref("load new xref format trailer\n"); - return pdf_parseindobj(&xref->trailer, xref->file, buf, cap, nil, nil, nil); + + error = pdf_parseindobj(&xref->trailer, xref->file, buf, cap, nil, nil, nil); + if (error) + return fz_rethrow(error, "cannot parse trailer (compressed)"); + return fz_okay; } static fz_error * readtrailer(pdf_xref *xref, char *buf, int cap) { - int n; + fz_error *error; int c; - n = fz_seek(xref->file, xref->startxref, 0); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, xref->startxref, 0); + if (error) + return fz_rethrow(error, "cannot seek to startxref"); c = fz_peekbyte(xref->file); + error = fz_readerror(xref->file); + if (error) + return fz_rethrow(error, "cannot read trailer"); + if (c == 'x') - return readoldtrailer(xref, buf, cap); + { + error = readoldtrailer(xref, buf, cap); + if (error) + return fz_rethrow(error, "cannot read trailer"); + } else if (c >= '0' && c <= '9') - return readnewtrailer(xref, buf, cap); + { + error = readnewtrailer(xref, buf, cap); + if (error) + return fz_rethrow(error, "cannot read trailer"); + } + else + { + return fz_throw("cannot recognize xref format"); + } - return fz_throw("syntaxerror: could not find xref"); + return fz_okay; } /* @@ -156,6 +201,7 @@ readtrailer(pdf_xref *xref, char *buf, int cap) static fz_error * readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) { + fz_error *error; int ofs, len; char *s; int n; @@ -165,9 +211,11 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) pdf_logxref("load old xref format\n"); - fz_readline(xref->file, buf, cap); + error = fz_readline(xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref marker"); if (strcmp(buf, "xref") != 0) - return fz_throw("syntaxerror: expected xref"); + return fz_throw("cannot find xref marker"); while (1) { @@ -175,9 +223,9 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) if (!(c >= '0' && c <= '9')) break; - n = fz_readline(xref->file, buf, cap); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_readline(xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref count"); s = buf; ofs = atoi(strsep(&s, " ")); @@ -186,17 +234,17 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') { - fz_warn("syntaxerror: broken xref section"); - fz_seek(xref->file, -(n + buf - s + 2), 1); + fz_warn("broken xref section. proceeding anyway."); + error = fz_seek(xref->file, -(n + buf - s + 2), 1); + if (error) + return fz_rethrow(error, "cannot seek to xref"); } for (i = 0; i < len; i++) { - n = fz_read(xref->file, (unsigned char *) buf, 20); - if (n < 0) - return fz_ioerror(xref->file); - if (n != 20) - return fz_throw("syntaxerror: truncated xref table"); + error = fz_read(&n, xref->file, buf, 20); + if (error) + return fz_rethrow(error, "cannot read xref table"); if (!xref->table[ofs + i].type) { s = buf; @@ -207,14 +255,22 @@ readoldxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) } } - t = pdf_lex(xref->file, (unsigned char *) buf, cap, &n); + error = pdf_lex(&t, xref->file, buf, cap, &n); + if (error) + return fz_rethrow(error, "cannot parse trailer"); if (t != PDF_TTRAILER) - return fz_throw("syntaxerror: expected trailer"); - t = pdf_lex(xref->file, (unsigned char *) buf, cap, &n); + return fz_throw("expected trailer marker"); + + error = pdf_lex(&t, xref->file, buf, cap, &n); + if (error) + return fz_rethrow(error, "cannot parse trailer"); if (t != PDF_TODICT) - return fz_throw("syntaxerror: expected trailer dictionary"); + return fz_throw("expected trailer dictionary"); - return pdf_parsedict(trailerp, xref->file, buf, cap); + error = pdf_parsedict(trailerp, xref->file, buf, cap); + if (error) + return fz_rethrow(error, "cannot parse trailer"); + return fz_okay; } static fz_error * @@ -232,10 +288,11 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) error = pdf_parseindobj(&trailer, xref->file, buf, cap, &oid, &gen, &stmofs); if (error) - return error; + return fz_rethrow(error, "cannot parse compressed xref stream object"); - if (oid < 0 || oid >= xref->len) { - error = fz_throw("rangecheck: object id out of range"); + if (oid < 0 || oid >= xref->len) + { + error = fz_throw("object id out of range"); goto cleanup; } @@ -245,15 +302,16 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) xref->table[oid].stmofs = stmofs; obj = fz_dictgets(trailer, "Size"); - if (!obj) { - error = fz_throw("syntaxerror: xref stream missing Size entry"); + if (!obj) + { + error = fz_throw("xref stream missing Size entry"); goto cleanup; } size = fz_toint(obj); obj = fz_dictgets(trailer, "W"); if (!obj) { - error = fz_throw("syntaxerror: xref stream missing W entry"); + error = fz_throw("xref stream missing W entry"); goto cleanup; } w0 = fz_toint(fz_arrayget(obj, 0)); @@ -271,13 +329,16 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) } if (i0 < 0 || i1 > xref->len) { - error = fz_throw("syntaxerror: xref stream has too many entries"); + error = fz_throw("xref stream has too many entries"); goto cleanup; } error = pdf_openstream(&stm, xref, oid, gen); if (error) + { + error = fz_rethrow(error, "cannot open compressed xref stream"); goto cleanup; + } for (i = i0; i < i0 + i1; i++) { @@ -287,7 +348,11 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) if (fz_peekbyte(stm) == EOF) { - error = fz_throw("syntaxerror: truncated xref stream"); + error = fz_readerror(stm); + if (error) + error = fz_rethrow(error, "truncated xref stream"); + else + error = fz_throw("truncated xref stream"); fz_dropstream(stm); goto cleanup; } @@ -299,6 +364,14 @@ readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) for (n = 0; n < w2; n++) c = (c << 8) + fz_readbyte(stm); + error = fz_readerror(stm); + if (error) + { + error = fz_rethrow(error, "truncated xref stream"); + fz_dropstream(stm); + goto cleanup; + } + if (!xref->table[i].type) { int t = w0 ? a : 1; @@ -322,20 +395,36 @@ cleanup: static fz_error * readxref(fz_obj **trailerp, pdf_xref *xref, int ofs, char *buf, int cap) { - int n; + fz_error *error; int c; - n = fz_seek(xref->file, ofs, 0); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, ofs, 0); + if (error) + return fz_rethrow(error, "cannot seek to xref"); c = fz_peekbyte(xref->file); + error = fz_readerror(xref->file); + if (error) + return fz_rethrow(error, "cannot read trailer"); + if (c == 'x') - return readoldxref(trailerp, xref, buf, cap); + { + error = readoldxref(trailerp, xref, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref (ofs=%d)", ofs); + } else if (c >= '0' && c <= '9') - return readnewxref(trailerp, xref, buf, cap); + { + error = readnewxref(trailerp, xref, buf, cap); + if (error) + return fz_rethrow(error, "cannot read xref (ofs=%d)", ofs); + } + else + { + return fz_throw("cannot recognize xref format"); + } - return fz_throw("syntaxerror: expected xref"); + return fz_okay; } static fz_error * @@ -348,7 +437,7 @@ readxrefsections(pdf_xref *xref, int ofs, char *buf, int cap) error = readxref(&trailer, xref, ofs, buf, cap); if (error) - return error; + return fz_rethrow(error, "cannot read xref section"); /* FIXME: do we overwrite free entries properly? */ xrefstm = fz_dictgets(trailer, "XrefStm"); @@ -357,7 +446,10 @@ readxrefsections(pdf_xref *xref, int ofs, char *buf, int cap) pdf_logxref("load xrefstm\n"); error = readxrefsections(xref, fz_toint(xrefstm), buf, cap); if (error) + { + error = fz_rethrow(error, "cannot read /XrefStm xref section"); goto cleanup; + } } prev = fz_dictgets(trailer, "Prev"); @@ -366,7 +458,10 @@ readxrefsections(pdf_xref *xref, int ofs, char *buf, int cap) pdf_logxref("load prev\n"); error = readxrefsections(xref, fz_toint(prev), buf, cap); if (error) + { + error = fz_rethrow(error, "cannot read /Prev xref section"); goto cleanup; + } } fz_dropobj(trailer); @@ -399,7 +494,7 @@ pdf_loadobjstm(pdf_xref *xref, int oid, int gen, char *buf, int cap) error = pdf_loadobject(&objstm, xref, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot load object stream object"); count = fz_toint(fz_dictgets(objstm, "N")); first = fz_toint(fz_dictgets(objstm, "First")); @@ -407,38 +502,49 @@ pdf_loadobjstm(pdf_xref *xref, int oid, int gen, char *buf, int cap) pdf_logxref(" count %d\n", count); oidbuf = fz_malloc(count * sizeof(int)); - if (!oidbuf) { error = fz_outofmem; goto cleanupobj; } + if (!oidbuf) + { + error = fz_throw("outofmem: object id buffer"); + goto cleanupobj; + } ofsbuf = fz_malloc(count * sizeof(int)); - if (!ofsbuf) { error = fz_outofmem; goto cleanupoid; } + if (!ofsbuf) + { + error = fz_throw("outofmem: offset buffer"); + goto cleanupoid; + } error = pdf_openstream(&stm, xref, oid, gen); if (error) + { + error = fz_rethrow(error, "cannot open object stream"); goto cleanupofs; + } for (i = 0; i < count; i++) { - t = pdf_lex(stm, (unsigned char *) buf, cap, &n); - if (t != PDF_TINT) + error = pdf_lex(&t, stm, buf, cap, &n); + if (error || t != PDF_TINT) { - error = fz_throw("syntaxerror: corrupt object stream"); + error = fz_rethrow(error, "corrupt object stream"); goto cleanupstm; } oidbuf[i] = atoi(buf); - t = pdf_lex(stm, (unsigned char *) buf, cap, &n); - if (t != PDF_TINT) + error = pdf_lex(&t, stm, buf, cap, &n); + if (error || t != PDF_TINT) { - error = fz_throw("syntaxerror: corrupt object stream"); + error = fz_rethrow(error, "corrupt object stream"); goto cleanupstm; } ofsbuf[i] = atoi(buf); } - n = fz_seek(stm, first, 0); - if (n < 0) + error = fz_seek(stm, first, 0); + if (error) { - error = fz_ioerror(stm); + error = fz_rethrow(error, "cannot seek in object stream"); goto cleanupstm; } @@ -448,11 +554,14 @@ pdf_loadobjstm(pdf_xref *xref, int oid, int gen, char *buf, int cap) error = pdf_parsestmobj(&obj, stm, buf, cap); if (error) + { + error = fz_rethrow(error, "cannot parse object %d in stream", i); goto cleanupstm; + } if (oidbuf[i] < 1 || oidbuf[i] >= xref->len) { - error = fz_throw("rangecheck: object number out of range"); + error = fz_throw("object id out of range (%d)", oidbuf[i]); goto cleanupstm; } @@ -495,23 +604,23 @@ pdf_loadxref(pdf_xref *xref, char *filename) error = fz_openrfile(&xref->file, filename); if (error) - return error; + return fz_rethrow(error, "cannot open file: '%s'", filename); error = loadversion(xref); if (error) - return error; + return fz_rethrow(error, "cannot read version marker"); error = readstartxref(xref); if (error) - return error; + return fz_rethrow(error, "cannot read startxref"); error = readtrailer(xref, buf, sizeof buf); if (error) - return error; + return fz_rethrow(error, "cannot read trailer"); size = fz_dictgets(xref->trailer, "Size"); if (!size) - return fz_throw("syntaxerror: trailer missing Size entry"); + return fz_throw("trailer missing Size entry"); pdf_logxref(" size %d\n", fz_toint(size)); @@ -521,7 +630,7 @@ pdf_loadxref(pdf_xref *xref, char *filename) xref->len = fz_toint(size); xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); if (!xref->table) - return fz_outofmem; + return fz_throw("outofmem: xref table"); for (i = 0; i < xref->len; i++) { @@ -536,8 +645,8 @@ pdf_loadxref(pdf_xref *xref, char *filename) error = readxrefsections(xref, xref->startxref, buf, sizeof buf); if (error) - return error; + return fz_rethrow(error, "cannot read xref"); - return nil; + return fz_okay; } diff --git a/mupdf/pdf_page.c b/mupdf/pdf_page.c index 25400f2f..f509737b 100644 --- a/mupdf/pdf_page.c +++ b/mupdf/pdf_page.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" static fz_error * runone(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) @@ -11,13 +11,16 @@ runone(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) error = pdf_openstream(&stm, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) - return error; + return fz_rethrow(error, "cannot open content stream %d", fz_tonum(stmref)); error = pdf_runcsi(csi, xref, rdb, stm); fz_dropstream(stm); - return error; + if (error) + return fz_rethrow(error, "cannot interpret content stream %d", fz_tonum(stmref)); + + return fz_okay; } /* we need to combine all sub-streams into one for pdf_runcsi @@ -31,18 +34,20 @@ runmany(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_obj *list) fz_buffer *big; fz_buffer *one; fz_obj *stm; - int n; int i; pdf_logpage("multiple content streams: %d\n", fz_arraylen(list)); error = fz_newbuffer(&big, 32 * 1024); if (error) - return error; + return fz_rethrow(error, "cannot create content buffer"); error = fz_openwbuffer(&file, big); if (error) - goto cleanup0; + { + error = fz_rethrow(error, "cannot open content buffer (write)"); + goto cleanupbuf; + } for (i = 0; i < fz_arraylen(list); i++) { @@ -51,37 +56,52 @@ runmany(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_obj *list) stm = fz_arrayget(list, i); error = pdf_loadstream(&one, xref, fz_tonum(stm), fz_togen(stm)); if (error) - goto cleanup1; + { + error = fz_rethrow(error, "cannot load content stream"); + goto cleanupstm; + } - n = fz_write(file, one->rp, one->wp - one->rp); + error = fz_write(file, one->rp, one->wp - one->rp); + if (error) + { + fz_dropbuffer(one); + error = fz_rethrow(error, "cannot write to content buffer"); + goto cleanupstm; + } fz_dropbuffer(one); - if (n == -1) + fz_printstr(file, " "); + if (error) { - error = fz_ioerror(file); - goto cleanup1; + error = fz_rethrow(error, "cannot write to content buffer"); + goto cleanupstm; } - - fz_printstr(file, " "); } fz_dropstream(file); error = fz_openrbuffer(&file, big); if (error) - goto cleanup0; + { + error = fz_rethrow(error, "cannot open content buffer (read)"); + goto cleanupbuf; + } error = pdf_runcsi(csi, xref, rdb, file); + if (error) + { + error = fz_rethrow(error, "cannot interpret content buffer"); + goto cleanupstm; + } fz_dropstream(file); fz_dropbuffer(big); + return fz_okay; - return error; - -cleanup1: +cleanupstm: fz_dropstream(file); -cleanup0: +cleanupbuf: fz_dropbuffer(big); return error; } @@ -95,13 +115,13 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref) error = pdf_newcsi(&csi, 0); if (error) - return error; + return fz_rethrow(error, "cannot create interpreter"); if (fz_isindirect(ref)) { error = pdf_loadindirect(&obj, xref, ref); if (error) - return error; + return fz_rethrow(error, "cannot load page contents (%d)", fz_tonum(ref)); if (fz_isarray(obj)) { @@ -114,8 +134,12 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref) error = runone(csi, xref, rdb, ref); fz_dropobj(obj); + if (error) - goto cleanup; + { + pdf_dropcsi(csi); + return fz_rethrow(error, "cannot interpret page contents (%d)", fz_tonum(ref)); + } } else if (fz_isarray(ref)) @@ -124,15 +148,20 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref) error = runone(csi, xref, rdb, fz_arrayget(ref, 0)); else error = runmany(csi, xref, rdb, ref); + + if (error) + { + pdf_dropcsi(csi); + return fz_rethrow(error, "cannot interpret page contents (%d)", fz_tonum(ref)); + } } *treep = csi->tree; csi->tree = nil; - error = nil; -cleanup: pdf_dropcsi(csi); - return error; + + return fz_okay; } fz_error * @@ -158,11 +187,11 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) if (!obj) obj = fz_dictgets(dict, "MediaBox"); if (!fz_isarray(obj)) - return fz_throw("syntaxerror: Page missing MediaBox"); + return fz_throw("cannot find page bounds"); bbox = pdf_torect(obj); pdf_logpage("bbox [%g %g %g %g]\n", - bbox.x0, bbox.y0, bbox.x1, bbox.y1); + bbox.x0, bbox.y0, bbox.x1, bbox.y1); obj = fz_dictgets(dict, "Rotate"); if (fz_isint(obj)) @@ -181,11 +210,11 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) { error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve annotations"); error = pdf_loadannots(&comments, &links, xref, obj); fz_dropobj(obj); if (error) - return error; + return fz_rethrow(error, "cannot load annotations"); } /* @@ -194,14 +223,14 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) obj = fz_dictgets(dict, "Resources"); if (!obj) - return fz_throw("syntaxerror: Page missing Resources"); + return fz_throw("cannot find page resources"); error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve page resources"); error = pdf_loadresources(&rdb, xref, obj); fz_dropobj(obj); if (error) - return error; + return fz_rethrow(error, "cannot load page resources"); /* * Interpret content stream to build display tree @@ -210,33 +239,30 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) obj = fz_dictgets(dict, "Contents"); error = loadpagecontents(&tree, xref, rdb, obj); - if (error) { + if (error) + { fz_dropobj(rdb); - return error; + return fz_rethrow(error, "cannot load page contents"); } - if (!getenv("DONTOPT")) + pdf_logpage("optimize tree\n"); + error = fz_optimizetree(tree); + if (error) { - if (getenv("SHOWTREE")) - fz_debugtree(tree); - - pdf_logpage("optimize tree\n"); - - error = fz_optimizetree(tree); - if (error) { - fz_dropobj(rdb); - return error; - } + fz_dropobj(rdb); + return fz_rethrow(error, "cannot optimize page display tree"); } + /* * Create page object */ - page = *pagep = fz_malloc(sizeof(pdf_page)); - if (!page) { + page = fz_malloc(sizeof(pdf_page)); + if (!page) + { fz_droptree(tree); fz_dropobj(rdb); - return fz_outofmem; + return fz_throw("outofmem: page struct"); } page->mediabox.x0 = MIN(bbox.x0, bbox.x1); @@ -252,20 +278,15 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) pdf_logpage("} %p\n", page); - if (getenv("SHOWTREE")) - fz_debugtree(tree); - - return nil; + *pagep = page; + return fz_okay; } void pdf_droppage(pdf_page *page) { pdf_logpage("drop page %p\n", page); -/* - if (page->comments) - pdf_dropcomment(page->comments); -*/ + /* if (page->comments) pdf_dropcomment(page->comments); */ if (page->links) pdf_droplink(page->links); fz_dropobj(page->resources); diff --git a/mupdf/pdf_pagetree.c b/mupdf/pdf_pagetree.c index f44e3ed9..47c0362b 100644 --- a/mupdf/pdf_pagetree.c +++ b/mupdf/pdf_pagetree.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" struct stuff { @@ -11,7 +11,7 @@ struct stuff static fz_error * loadpagetree(pdf_xref *xref, pdf_pagetree *pages, - struct stuff inherit, fz_obj *obj, fz_obj *ref) + struct stuff inherit, fz_obj *obj, fz_obj *ref) { fz_error *error; fz_obj *type; @@ -28,28 +28,28 @@ loadpagetree(pdf_xref *xref, pdf_pagetree *pages, { pdf_logpage("inherit resources (%d)\n", pages->cursor); error = fz_dictputs(obj, "Resources", inherit.resources); - if (error) return error; + if (error) return fz_rethrow(error, "cannot inherit page tree resources"); } if (inherit.mediabox && !fz_dictgets(obj, "MediaBox")) { pdf_logpage("inherit mediabox (%d)\n", pages->cursor); error = fz_dictputs(obj, "MediaBox", inherit.mediabox); - if (error) return error; + if (error) return fz_rethrow(error, "cannot inherit page tree mediabox"); } if (inherit.cropbox && !fz_dictgets(obj, "CropBox")) { pdf_logpage("inherit cropbox (%d)\n", pages->cursor); error = fz_dictputs(obj, "CropBox", inherit.cropbox); - if (error) return error; + if (error) return fz_rethrow(error, "cannot inherit page tree cropbox"); } if (inherit.rotate && !fz_dictgets(obj, "Rotate")) { pdf_logpage("inherit rotate (%d)\n", pages->cursor); error = fz_dictputs(obj, "Rotate", inherit.rotate); - if (error) return error; + if (error) return fz_rethrow(error, "cannot inherit page tree rotate"); } pages->pref[pages->cursor] = fz_keepobj(ref); @@ -74,7 +74,7 @@ loadpagetree(pdf_xref *xref, pdf_pagetree *pages, kids = fz_dictgets(obj, "Kids"); error = pdf_resolve(&kids, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve /Kids"); pdf_logpage("subtree %d {\n", fz_arraylen(kids)); @@ -83,11 +83,11 @@ loadpagetree(pdf_xref *xref, pdf_pagetree *pages, kref = fz_arrayget(kids, i); error = pdf_loadindirect(&kobj, xref, kref); - if (error) { fz_dropobj(kids); return error; } + if (error) { fz_dropobj(kids); return fz_rethrow(error, "cannot load kid"); } error = loadpagetree(xref, pages, inherit, kobj, kref); fz_dropobj(kobj); - if (error) { fz_dropobj(kids); return error; } + if (error) { fz_dropobj(kids); return fz_rethrow(error, "cannot load subtree"); } } fz_dropobj(kids); @@ -95,7 +95,7 @@ loadpagetree(pdf_xref *xref, pdf_pagetree *pages, pdf_logpage("}\n"); } - return nil; + return fz_okay; } void @@ -132,17 +132,17 @@ pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref) ref = fz_dictgets(trailer, "Root"); error = pdf_loadindirect(&catalog, xref, ref); - if (error) goto cleanup; + if (error) { error = fz_rethrow(error, "cannot load Root object"); goto cleanup; } ref = fz_dictgets(catalog, "Pages"); error = pdf_loadindirect(&pages, xref, ref); - if (error) goto cleanup; + if (error) { error = fz_rethrow(error, "cannot load Pages object"); goto cleanup; } ref = fz_dictgets(pages, "Count"); count = fz_toint(ref); p = fz_malloc(sizeof(pdf_pagetree)); - if (!p) { error = fz_outofmem; goto cleanup; } + if (!p) { error = fz_throw("outofmem: page tree struct"); goto cleanup; } pdf_logpage("load pagetree %p {\n", p); pdf_logpage("count %d\n", count); @@ -153,13 +153,13 @@ pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref) p->cursor = 0; p->pref = fz_malloc(sizeof(fz_obj*) * count); - if (!p->pref) { error = fz_outofmem; goto cleanup; } + if (!p->pref) { error = fz_throw("outofmem: page tree reference array"); goto cleanup; } p->pobj = fz_malloc(sizeof(fz_obj*) * count); - if (!p->pobj) { error = fz_outofmem; goto cleanup; } + if (!p->pobj) { error = fz_throw("outofmem: page tree object array"); goto cleanup; } error = loadpagetree(xref, p, inherit, pages, ref); - if (error) goto cleanup; + if (error) { error = fz_rethrow(error, "cannot load page tree"); goto cleanup; } fz_dropobj(pages); fz_dropobj(catalog); @@ -167,7 +167,7 @@ pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref) pdf_logpage("}\n", count); *pp = p; - return nil; + return fz_okay; cleanup: if (pages) fz_dropobj(pages); diff --git a/mupdf/pdf_parse.c b/mupdf/pdf_parse.c index 91a5892d..2353ba4e 100644 --- a/mupdf/pdf_parse.c +++ b/mupdf/pdf_parse.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" fz_rect pdf_torect(fz_obj *array) { @@ -30,7 +30,7 @@ fz_matrix pdf_tomatrix(fz_obj *array) fz_error * pdf_toutf8(char **dstp, fz_obj *src) { - unsigned char *srcptr = (unsigned char *) fz_tostrbuf(src); + unsigned char *srcptr = fz_tostrbuf(src); char *dstptr; int srclen = fz_tostrlen(src); int dstlen = 0; @@ -47,7 +47,7 @@ pdf_toutf8(char **dstp, fz_obj *src) dstptr = *dstp = fz_malloc(dstlen + 1); if (!dstptr) - return fz_outofmem; + return fz_throw("outofmem: utf-8 string"); for (i = 2; i < srclen; i += 2) { @@ -63,7 +63,7 @@ pdf_toutf8(char **dstp, fz_obj *src) dstptr = *dstp = fz_malloc(dstlen + 1); if (!dstptr) - return fz_outofmem; + return fz_throw("outofmem: utf-8 string"); for (i = 0; i < srclen; i++) { @@ -73,13 +73,13 @@ pdf_toutf8(char **dstp, fz_obj *src) } *dstptr = '\0'; - return nil; + return fz_okay; } fz_error * pdf_toucs2(unsigned short **dstp, fz_obj *src) { - unsigned char *srcptr = (unsigned char *) fz_tostrbuf(src); + unsigned char *srcptr = fz_tostrbuf(src); unsigned short *dstptr; int srclen = fz_tostrlen(src); int i; @@ -88,7 +88,7 @@ pdf_toucs2(unsigned short **dstp, fz_obj *src) { dstptr = *dstp = fz_malloc(((srclen - 2) / 2 + 1) * sizeof(short)); if (!dstptr) - return fz_outofmem; + return fz_throw("outofmem: ucs-2 string"); for (i = 2; i < srclen; i += 2) *dstptr++ = (srcptr[i] << 8) | srcptr[i+1]; } @@ -97,13 +97,13 @@ pdf_toucs2(unsigned short **dstp, fz_obj *src) { dstptr = *dstp = fz_malloc((srclen + 1) * sizeof(short)); if (!dstptr) - return fz_outofmem; + return fz_throw("outofmem: ucs-2 string"); for (i = 0; i < srclen; i++) *dstptr++ = pdf_docencoding[srcptr[i]]; } *dstptr = '\0'; - return nil; + return fz_okay; } fz_error * @@ -116,30 +116,37 @@ pdf_parsearray(fz_obj **op, fz_stream *file, char *buf, int cap) int tok, len; error = fz_newarray(op, 4); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create array"); ary = *op; while (1) { - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + goto cleanup; if (tok != PDF_TINT && tok != PDF_TR) { if (n > 0) { error = fz_newint(&obj, a); - if (error) goto cleanup; + if (error) + goto cleanup; error = fz_arraypush(ary, obj); - if (error) goto cleanup; + if (error) + goto cleanup; fz_dropobj(obj); obj = nil; } if (n > 1) { error = fz_newint(&obj, b); - if (error) goto cleanup; + if (error) + goto cleanup; error = fz_arraypush(ary, obj); - if (error) goto cleanup; + if (error) + goto cleanup; fz_dropobj(obj); obj = nil; } @@ -149,9 +156,11 @@ pdf_parsearray(fz_obj **op, fz_stream *file, char *buf, int cap) if (tok == PDF_TINT && n == 2) { error = fz_newint(&obj, a); - if (error) goto cleanup; + if (error) + goto cleanup; error = fz_arraypush(ary, obj); - if (error) goto cleanup; + if (error) + goto cleanup; fz_dropobj(obj); obj = nil; a = b; @@ -186,12 +195,14 @@ pdf_parsearray(fz_obj **op, fz_stream *file, char *buf, int cap) case PDF_TNULL: error = fz_newnull(&obj); break; default: goto cleanup; } - if (error) goto cleanup; + if (error) + goto cleanup; if (obj) { error = fz_arraypush(ary, obj); - if (error) goto cleanup; + if (error) + goto cleanup; fz_dropobj(obj); } @@ -201,8 +212,7 @@ pdf_parsearray(fz_obj **op, fz_stream *file, char *buf, int cap) cleanup: if (obj) fz_dropobj(obj); if (ary) fz_dropobj(ary); - if (error) return error; - return fz_throw("syntaxerror: corrupt array"); + return fz_rethrow(error, "cannot parse array"); } fz_error * @@ -216,12 +226,15 @@ pdf_parsedict(fz_obj **op, fz_stream *file, char *buf, int cap) int a, b; error = fz_newdict(op, 8); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot create dict"); dict = *op; while (1) { - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + goto cleanup; skip: if (tok == PDF_TCDICT) @@ -235,9 +248,12 @@ skip: goto cleanup; error = fz_newname(&key, buf); - if (error) goto cleanup; + if (error) + goto cleanup; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + goto cleanup; switch (tok) { @@ -250,33 +266,35 @@ skip: case PDF_TFALSE: error = fz_newbool(&val, 0); break; case PDF_TNULL: error = fz_newnull(&val); break; case PDF_TINT: - a = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); - if (tok == PDF_TCDICT || tok == PDF_TNAME || - (tok == PDF_TKEYWORD && !strcmp(buf, "ID"))) - { - error = fz_newint(&val, a); - if (error) goto cleanup; - error = fz_dictput(dict, key, val); - if (error) goto cleanup; - fz_dropobj(val); - fz_dropobj(key); - key = val = nil; - goto skip; - } - if (tok == PDF_TINT) - { - b = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); - if (tok == PDF_TR) - { - error = fz_newindirect(&val, a, b); - break; - } - } - goto cleanup; + a = atoi(buf); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; + if (tok == PDF_TCDICT || tok == PDF_TNAME || + (tok == PDF_TKEYWORD && !strcmp(buf, "ID"))) + { + error = fz_newint(&val, a); + if (error) goto cleanup; + error = fz_dictput(dict, key, val); + if (error) goto cleanup; + fz_dropobj(val); + fz_dropobj(key); + key = val = nil; + goto skip; + } + if (tok == PDF_TINT) + { + b = atoi(buf); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; + if (tok == PDF_TR) + { + error = fz_newindirect(&val, a, b); + break; + } + } + goto cleanup; default: - goto cleanup; + goto cleanup; } if (error) goto cleanup; @@ -293,31 +311,36 @@ cleanup: if (key) fz_dropobj(key); if (val) fz_dropobj(val); if (dict) fz_dropobj(dict); - if (error) return error; - return fz_throw("syntaxerror: corrupt dictionary"); + return fz_rethrow(error, "cannot parse dict"); } fz_error * pdf_parsestmobj(fz_obj **op, fz_stream *file, char *buf, int cap) { + fz_error *error; int tok, len; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + return fz_rethrow(error, "cannot parse token in object stream"); switch (tok) { - case PDF_TOARRAY: return pdf_parsearray(op, file, buf, cap); - case PDF_TODICT: return pdf_parsedict(op, file, buf, cap); - case PDF_TNAME: return fz_newname(op, buf); - case PDF_TREAL: return fz_newreal(op, atof(buf)); - case PDF_TSTRING: return fz_newstring(op, buf, len); - case PDF_TTRUE: return fz_newbool(op, 1); - case PDF_TFALSE: return fz_newbool(op, 0); - case PDF_TNULL: return fz_newnull(op); - case PDF_TINT: return fz_newint(op, atoi(buf)); + case PDF_TOARRAY: error = pdf_parsearray(op, file, buf, cap); break; + case PDF_TODICT: error = pdf_parsedict(op, file, buf, cap); break; + case PDF_TNAME: error = fz_newname(op, buf); break; + case PDF_TREAL: error = fz_newreal(op, atof(buf)); break; + case PDF_TSTRING: error = fz_newstring(op, buf, len); break; + case PDF_TTRUE: error = fz_newbool(op, 1); break; + case PDF_TFALSE: error = fz_newbool(op, 0); break; + case PDF_TNULL: error = fz_newnull(op); break; + case PDF_TINT: error = fz_newint(op, atoi(buf)); break; + default: return fz_throw("unknown token in object stream"); } - return fz_throw("syntaxerror: corrupt object stream"); + if (error) + return fz_rethrow(error, "cannot parse object stream"); + return fz_okay; } fz_error * @@ -330,34 +353,38 @@ pdf_parseindobj(fz_obj **op, fz_stream *file, char *buf, int cap, int tok, len; int a, b; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); - if (tok != PDF_TINT) + error = pdf_lex(&tok, file, buf, cap, &len); + if (error || tok != PDF_TINT) goto cleanup; oid = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); - if (tok != PDF_TINT) + error = pdf_lex(&tok, file, buf, cap, &len); + if (error || tok != PDF_TINT) goto cleanup; gid = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); - if (tok != PDF_TOBJ) + error = pdf_lex(&tok, file, buf, cap, &len); + if (error || tok != PDF_TOBJ) + goto cleanup; + + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); switch (tok) { - case PDF_TOARRAY: error = pdf_parsearray(&obj, file, buf, cap); break; - case PDF_TODICT: error = pdf_parsedict(&obj, file, buf, cap); break; - case PDF_TNAME: error = fz_newname(&obj, buf); break; - case PDF_TREAL: error = fz_newreal(&obj, atof(buf)); break; - case PDF_TSTRING: error = fz_newstring(&obj, buf, len); break; - case PDF_TTRUE: error = fz_newbool(&obj, 1); break; - case PDF_TFALSE: error = fz_newbool(&obj, 0); break; - case PDF_TNULL: error = fz_newnull(&obj); break; - case PDF_TINT: + case PDF_TOARRAY: error = pdf_parsearray(&obj, file, buf, cap); break; + case PDF_TODICT: error = pdf_parsedict(&obj, file, buf, cap); break; + case PDF_TNAME: error = fz_newname(&obj, buf); break; + case PDF_TREAL: error = fz_newreal(&obj, atof(buf)); break; + case PDF_TSTRING: error = fz_newstring(&obj, buf, len); break; + case PDF_TTRUE: error = fz_newbool(&obj, 1); break; + case PDF_TFALSE: error = fz_newbool(&obj, 0); break; + case PDF_TNULL: error = fz_newnull(&obj); break; + case PDF_TINT: a = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; if (tok == PDF_TSTREAM || tok == PDF_TENDOBJ) { error = fz_newint(&obj, a); @@ -367,7 +394,8 @@ pdf_parseindobj(fz_obj **op, fz_stream *file, char *buf, int cap, if (tok == PDF_TINT) { b = atoi(buf); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; if (tok == PDF_TR) { error = fz_newindirect(&obj, a, b); @@ -375,12 +403,13 @@ pdf_parseindobj(fz_obj **op, fz_stream *file, char *buf, int cap, } } goto cleanup; - default: + default: goto cleanup; } if (error) goto cleanup; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) goto cleanup; skip: if (tok == PDF_TSTREAM) @@ -390,10 +419,13 @@ skip: { c = fz_peekbyte(file); if (c != '\n') - fz_warn("syntaxerror: DOS format line ending after stream keyword (%d %d)\n", oid, gid); + fz_warn("syntaxerror: corrupt pdf stream (%d %d)\n", oid, gid); else c = fz_readbyte(file); } + error = fz_readerror(file); + if (error) + goto cleanup; stmofs = fz_tell(file); } else if (tok == PDF_TENDOBJ) @@ -408,8 +440,10 @@ skip: return nil; cleanup: - if (obj) fz_dropobj(obj); - if (error) return error; - return fz_throw("syntaxerror: corrupt indirect object (%d %d)", oid, gid); + if (obj) + fz_dropobj(obj); + if (error) + return fz_rethrow(error, "cannot parse indirect object (%d %d)", oid, gid); + return fz_throw("cannot parse indirect object (%d %d)", oid, gid); } diff --git a/mupdf/pdf_pattern.c b/mupdf/pdf_pattern.c index 8b9e9bc4..c5668884 100644 --- a/mupdf/pdf_pattern.c +++ b/mupdf/pdf_pattern.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" pdf_pattern * pdf_keeppattern(pdf_pattern *pat) @@ -32,14 +32,14 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref if ((*patp = pdf_finditem(xref->store, PDF_KPATTERN, stmref))) { pdf_keeppattern(*patp); - return nil; + return fz_okay; } pdf_logrsrc("load pattern %d %d {\n", fz_tonum(stmref), fz_togen(stmref)); pat = fz_malloc(sizeof(pdf_pattern)); if (!pat) - return fz_outofmem; + return fz_throw("outofmem: pattern struct"); pat->tree = nil; pat->ismask = fz_toint(fz_dictgets(dict, "PaintType")) == 2; @@ -54,8 +54,8 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref pat->bbox = pdf_torect(obj); pdf_logrsrc("bbox [%g %g %g %g]\n", - pat->bbox.x0, pat->bbox.y0, - pat->bbox.x1, pat->bbox.y1); + pat->bbox.x0, pat->bbox.y0, + pat->bbox.x1, pat->bbox.y1); obj = fz_dictgets(dict, "Matrix"); if (obj) @@ -64,9 +64,9 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref pat->matrix = fz_identity(); pdf_logrsrc("matrix [%g %g %g %g %g %g]\n", - pat->matrix.a, pat->matrix.b, - pat->matrix.c, pat->matrix.d, - pat->matrix.e, pat->matrix.f); + pat->matrix.a, pat->matrix.b, + pat->matrix.c, pat->matrix.d, + pat->matrix.e, pat->matrix.f); /* * Resources @@ -74,20 +74,26 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref obj = fz_dictgets(dict, "Resources"); if (!obj) { - error = fz_throw("syntaxerror: Pattern missing Resources"); + error = fz_throw("cannot find Resources dictionary"); goto cleanup; } error = pdf_resolve(&obj, xref); if (error) + { + error = fz_rethrow(error, "cannot resolve resource dictionary"); goto cleanup; + } error = pdf_loadresources(&resources, xref, obj); fz_dropobj(obj); if (error) + { + error = fz_rethrow(error, "cannot load resources"); goto cleanup; + } /* * Content stream @@ -97,18 +103,27 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref error = pdf_newcsi(&csi, pat->ismask); if (error) + { + error = fz_rethrow(error, "cannot create interpreter"); goto cleanup; + } error = pdf_openstream(&stm, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) - goto cleanup2; + { + error = fz_rethrow(error, "cannot open pattern stream %d", fz_tonum(stmref)); + goto cleanupcsi; + } error = pdf_runcsi(csi, xref, resources, stm); fz_dropstream(stm); if (error) - goto cleanup2; + { + error = fz_rethrow(error, "cannot interpret pattern stream %d", fz_tonum(stmref)); + goto cleanupcsi; + } pat->tree = csi->tree; csi->tree = nil; @@ -118,18 +133,26 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref fz_dropobj(resources); pdf_logrsrc("optimize tree\n"); - fz_optimizetree(pat->tree); + error = fz_optimizetree(pat->tree); + if (error) + { + error = fz_rethrow(error, "cannot optimize pattern tree"); + goto cleanup; + } pdf_logrsrc("}\n"); error = pdf_storeitem(xref->store, PDF_KPATTERN, stmref, pat); if (error) + { + error = fz_rethrow(error, "cannot store pattern resource"); goto cleanup; + } *patp = pat; - return nil; + return fz_okay; -cleanup2: +cleanupcsi: pdf_dropcsi(csi); cleanup: pdf_droppattern(pat); diff --git a/mupdf/pdf_repair.c b/mupdf/pdf_repair.c index e350cd31..ffced0e0 100644 --- a/mupdf/pdf_repair.c +++ b/mupdf/pdf_repair.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* * open pdf and scan objects to reconstruct xref table @@ -16,7 +16,7 @@ struct entry static fz_error * parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, - int *isroot, int *isinfo) + int *isroot, int *isinfo) { fz_error *error; fz_obj *dict = nil; @@ -24,17 +24,18 @@ parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, fz_obj *filter; fz_obj *type; int tok, len; + int n; *stmlen = -1; *isroot = 0; *isinfo = 0; - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); if (tok == PDF_TODICT) { error = pdf_parsedict(&dict, file, buf, cap); if (error) - return error; + return fz_rethrow(error, "cannot parse object"); } if (fz_isdict(dict)) @@ -45,7 +46,10 @@ parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, filter = fz_dictgets(dict, "Filter"); if (fz_isname(filter) && !strcmp(fz_toname(filter), "Standard")) + { + fz_dropobj(dict); return fz_throw("cannot repair encrypted files"); + } if (fz_dictgets(dict, "Producer")) if (fz_dictgets(dict, "Creator")) @@ -53,11 +57,15 @@ parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, *isinfo = 1; } - while ( tok != PDF_TSTREAM && + while ( tok != PDF_TSTREAM && tok != PDF_TENDOBJ && tok != PDF_TERROR && tok != PDF_TEOF ) - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + { + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + return fz_rethrow(error, "cannot scan for endobj or stream token"); + } if (tok == PDF_TSTREAM) { @@ -68,19 +76,34 @@ parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, fz_readbyte(file); } + error = fz_readerror(file); + if (error) + return fz_rethrow(error, "cannot read from file"); + *stmofs = fz_tell(file); + if (*stmofs < 0) + return fz_throw("cannot seek in file"); length = fz_dictgets(dict, "Length"); if (fz_isint(length)) { - fz_seek(file, *stmofs + fz_toint(length), 0); - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = fz_seek(file, *stmofs + fz_toint(length), 0); + if (error) + return fz_rethrow(error, "cannot seek in file"); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + return fz_rethrow(error, "cannot scan for endstream token"); if (tok == PDF_TENDSTREAM) goto atobjend; - fz_seek(file, *stmofs, 0); + error = fz_seek(file, *stmofs, 0); + if (error) + return fz_rethrow(error, "cannot seek in file"); } - fz_read(file, (unsigned char *) buf, 9); + error = fz_read(&n, file, buf, 9); + if (error) + return fz_rethrow(error, "cannot read from file"); + while (memcmp(buf, "endstream", 9) != 0) { c = fz_readbyte(file); @@ -90,10 +113,16 @@ parseobj(fz_stream *file, char *buf, int cap, int *stmofs, int *stmlen, buf[8] = c; } + error = fz_readerror(file); + if (error) + return fz_rethrow(error, "cannot read from file"); + *stmlen = fz_tell(file) - *stmofs - 9; atobjend: - tok = pdf_lex(file, (unsigned char *) buf, cap, &len); + error = pdf_lex(&tok, file, buf, cap, &len); + if (error) + return fz_rethrow(error, "cannot scan for endobj token"); if (tok == PDF_TENDOBJ) ; } @@ -101,7 +130,7 @@ atobjend: if (dict) fz_dropobj(dict); - return nil; + return fz_okay; } fz_error * @@ -129,7 +158,7 @@ pdf_repairxref(pdf_xref *xref, char *filename) error = fz_openrfile(&file, filename); if (error) - return error; + return fz_rethrow(error, "cannot open file '%s'", filename); pdf_logxref("repairxref '%s' %p\n", filename, xref); @@ -141,13 +170,27 @@ pdf_repairxref(pdf_xref *xref, char *filename) listcap = 1024; list = fz_malloc(listcap * sizeof(struct entry)); if (!list) + { + error = fz_throw("outofmem: reparation object list"); goto cleanup; + } while (1) { tmpofs = fz_tell(file); + if (tmpofs < 0) + { + error = fz_throw("cannot tell in file"); + goto cleanup; + } + + error = pdf_lex(&tok, file, buf, sizeof buf, &len); + if (error) + { + error = fz_rethrow(error, "cannot scan for objects"); + goto cleanup; + } - tok = pdf_lex(file, (unsigned char *) buf, sizeof buf, &len); if (tok == PDF_TINT) { oidofs = genofs; @@ -160,7 +203,10 @@ pdf_repairxref(pdf_xref *xref, char *filename) { error = parseobj(file, buf, sizeof buf, &stmofs, &stmlen, &isroot, &isinfo); if (error) + { + error = fz_rethrow(error, "cannot parse object"); goto cleanup; + } if (isroot) { pdf_logxref("found catalog: %d %d\n", oid, gen); @@ -180,7 +226,7 @@ pdf_repairxref(pdf_xref *xref, char *filename) listcap = listcap * 2; newlist = fz_realloc(list, listcap * sizeof(struct entry)); if (!newlist) { - error = fz_outofmem; + error = fz_throw("outofmem: resize reparation object list"); goto cleanup; } list = newlist; @@ -206,22 +252,25 @@ pdf_repairxref(pdf_xref *xref, char *filename) if (rootoid == 0) { - error = fz_throw("syntaxerror: could not find catalog"); + error = fz_throw("cannot find catalog object"); goto cleanup; } error = fz_packobj(&xref->trailer, - "<< /Size %i /Root %r >>", - maxoid + 1, rootoid, rootgen); + "<< /Size %i /Root %r >>", + maxoid + 1, rootoid, rootgen); if (error) + { + error = fz_rethrow(error, "cannot create new trailer"); goto cleanup; + } xref->len = maxoid + 1; xref->cap = xref->len; xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); if (!xref->table) { - error = fz_outofmem; + error = fz_throw("outofmem: xref table"); goto cleanup; } @@ -259,21 +308,42 @@ pdf_repairxref(pdf_xref *xref, char *filename) fz_obj *dict, *length; pdf_logxref("correct stream length %d %d = %d\n", - list[i].oid, list[i].gen, list[i].stmlen); + list[i].oid, list[i].gen, list[i].stmlen); error = pdf_loadobject(&dict, xref, list[i].oid, list[i].gen); if (error) + { + error = fz_rethrow(error, "cannot load stream object"); goto cleanup; + } error = fz_newint(&length, list[i].stmlen); if (error) + { + fz_dropobj(dict); + error = fz_rethrow(error, "cannot create integer object"); goto cleanup; + } + error = fz_dictputs(dict, "Length", length); if (error) + { + fz_dropobj(length); + fz_dropobj(dict); + error = fz_rethrow(error, "cannot update stream length"); goto cleanup; + } - pdf_updateobject(xref, list[i].oid, list[i].gen, dict); + error = pdf_updateobject(xref, list[i].oid, list[i].gen, dict); + if (error) + { + fz_dropobj(length); + fz_dropobj(dict); + error = fz_rethrow(error, "cannot update stream object"); + goto cleanup; + } + fz_dropobj(length); fz_dropobj(dict); } } @@ -291,8 +361,7 @@ pdf_repairxref(pdf_xref *xref, char *filename) } fz_free(list); - - return nil; + return fz_okay; cleanup: fz_dropstream(file); diff --git a/mupdf/pdf_resources.c b/mupdf/pdf_resources.c index 2ea688c1..3d5503f6 100644 --- a/mupdf/pdf_resources.c +++ b/mupdf/pdf_resources.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* @@ -53,15 +53,15 @@ preloadcolorspace(pdf_xref *xref, fz_obj *ref) fz_obj *obj = ref; if (pdf_finditem(xref->store, PDF_KCOLORSPACE, ref)) - return nil; + return fz_okay; error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve colorspace resource %d", fz_tonum(ref)); error = pdf_loadcolorspace(&colorspace, xref, obj); fz_dropobj(obj); if (error) - return error; + return fz_rethrow(error, "cannot load colorspace resource %d", fz_tonum(ref)); pdf_logrsrc("rsrc colorspace %s\n", colorspace->name); @@ -69,10 +69,10 @@ preloadcolorspace(pdf_xref *xref, fz_obj *ref) if (error) { fz_dropcolorspace(colorspace); - return error; + return fz_rethrow(error, "cannot store colorspace resource"); } - return nil; + return fz_okay; } static fz_error * @@ -86,7 +86,7 @@ preloadpattern(pdf_xref *xref, fz_obj *ref) error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve pattern/shade resource %d", fz_tonum(ref)); type = fz_dictgets(obj, "PatternType"); @@ -94,20 +94,24 @@ preloadpattern(pdf_xref *xref, fz_obj *ref) { error = pdf_loadpattern(&pattern, xref, obj, ref); fz_dropobj(obj); - return error; + if (error) + return fz_rethrow(error, "cannot load pattern resource %d", fz_tonum(ref)); + return fz_okay; } else if (fz_toint(type) == 2) { error = pdf_loadshade(&shade, xref, obj, ref); fz_dropobj(obj); - return error; + if (error) + return fz_rethrow(error, "cannot load shade resource %d", fz_tonum(ref)); + return fz_okay; } else { fz_dropobj(obj); - return fz_throw("syntaxerror: unknown Pattern type"); + return fz_throw("unknown pattern resource type"); } } @@ -118,10 +122,10 @@ preloadshading(pdf_xref *xref, fz_obj *ref) fz_shade *shade; fz_obj *obj = ref; error = pdf_resolve(&obj, xref); - if (error) return error; + if (error) return fz_rethrow(error, "cannot resolve shade resource %d", fz_tonum(ref)); error = pdf_loadshade(&shade, xref, obj, ref); fz_dropobj(obj); - return error; + return fz_rethrow(error, "cannot load shade resource %d", fz_tonum(ref)); } static fz_error * @@ -135,7 +139,7 @@ preloadxobject(pdf_xref *xref, fz_obj *ref) error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve xobject/image resource %d", fz_tonum(ref)); subtype = fz_dictgets(obj, "Subtype"); @@ -143,20 +147,24 @@ preloadxobject(pdf_xref *xref, fz_obj *ref) { error = pdf_loadxobject(&xobject, xref, obj, ref); fz_dropobj(obj); - return error; + if (error) + return fz_rethrow(error, "cannot load xobject resource %d", fz_tonum(ref)); + return fz_okay; } else if (!strcmp(fz_toname(subtype), "Image")) { error = pdf_loadimage(&image, xref, obj, ref); fz_dropobj(obj); - return error; + if (error) + return fz_rethrow(error, "cannot load image resource %d", fz_tonum(ref)); + return fz_okay; } else { fz_dropobj(obj); - return fz_throw("syntaxerror: unknown XObject subtype"); + return fz_throw("unknown xobject resource type"); } } @@ -168,9 +176,11 @@ preloadfont(pdf_xref *xref, fz_obj *ref) fz_obj *obj = ref; error = pdf_resolve(&obj, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve font resource %d", fz_tonum(ref)); error = pdf_loadfont(&font, xref, obj, ref); - return error; + if (error) + return fz_rethrow(error, "cannot load font resource %d", fz_tonum(ref)); + return fz_okay; } static fz_error * @@ -193,7 +203,7 @@ scanfonts(pdf_xref *xref, fz_obj *rdb) pdf_logrsrc("extgstate font\n"); error = preloadfont(xref, fz_arrayget(obj, 0)); if (error) - return error; + return fz_rethrow(error, "cannot preload font listed in ExtGState"); } } } @@ -206,11 +216,11 @@ scanfonts(pdf_xref *xref, fz_obj *rdb) obj = fz_dictgetval(dict, i); error = preloadfont(xref, obj); if (error) - return error; + return fz_rethrow(error, "cannot preload font resource"); } } - return nil; + return fz_okay; } static fz_error * @@ -223,7 +233,7 @@ copyresolved(fz_obj **outp, pdf_xref *xref, fz_obj *dict) error = fz_newdict(©, fz_dictlen(dict)); if (error) - return error; + return fz_rethrow(error, "cannot create dictionary"); for (i = 0; i < fz_dictlen(dict); i++) { @@ -234,26 +244,31 @@ copyresolved(fz_obj **outp, pdf_xref *xref, fz_obj *dict) { error = pdf_loadindirect(&obj, xref, val); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load object"); + } error = fz_dictput(copy, key, obj); fz_dropobj(obj); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot save object"); + } } else { error = fz_dictput(copy, key, val); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot copy object"); + } } } *outp = copy; - return nil; - -cleanup: - fz_dropobj(copy); - return error; + return fz_okay; } fz_error * @@ -275,7 +290,7 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) { error = pdf_newstore(&xref->store); if (error) - return error; + return fz_rethrow(error, "cannot create resource store"); } pdf_logrsrc("load resources {\n"); @@ -286,18 +301,24 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) error = copyresolved(©, xref, orig); if (error) - return error; + return fz_rethrow(error, "cannot resolve indirect objects"); old = fz_dictgets(copy, "ExtGState"); if (old) { error = copyresolved(&new, xref, old); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot resolve indirect objects"); + } error = fz_dictputs(copy, "ExtGState", new); fz_dropobj(new); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot copy extgstate"); + } } /* @@ -310,9 +331,12 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) for (i = 0; i < fz_dictlen(dict); i++) { obj = fz_dictgetval(dict, i); - error = preloadcolorspace(xref, obj); - if (error) - return error; + error = preloadcolorspace(xref, obj); + if (error) + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load colorspace resource"); + } } } @@ -326,9 +350,12 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) for (i = 0; i < fz_dictlen(dict); i++) { obj = fz_dictgetval(dict, i); - error = preloadpattern(xref, obj); - if (error) - return error; + error = preloadpattern(xref, obj); + if (error) + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load pattern resource"); + } } } @@ -338,9 +365,12 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) for (i = 0; i < fz_dictlen(dict); i++) { obj = fz_dictgetval(dict, i); - error = preloadshading(xref, obj); - if (error) - return error; + error = preloadshading(xref, obj); + if (error) + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load shade resource"); + } } } @@ -354,9 +384,12 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) for (i = 0; i < fz_dictlen(dict); i++) { obj = fz_dictgetval(dict, i); - error = preloadxobject(xref, obj); - if (error) - return error; + error = preloadxobject(xref, obj); + if (error) + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load xobject resource"); + } } } @@ -366,15 +399,14 @@ pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) error = scanfonts(xref, copy); if (error) - goto cleanup; + { + fz_dropobj(copy); + return fz_rethrow(error, "cannot load font resources"); + } pdf_logrsrc("}\n"); *rdbp = copy; - return nil; - -cleanup: - fz_dropobj(copy); - return error; + return fz_okay; } diff --git a/mupdf/pdf_save.c b/mupdf/pdf_save.c index 0bcb8ac1..1338493d 100644 --- a/mupdf/pdf_save.c +++ b/mupdf/pdf_save.c @@ -1,5 +1,7 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" + +/* TODO: error check prints */ #define TIGHT 1 @@ -19,12 +21,12 @@ writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen { error = pdf_cryptstream(&ef, encrypt, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot create encryption filter"); - error = fz_openrfilter(&dststm, ef, out); + error = fz_openwfilter(&dststm, ef, out); fz_dropfilter(ef); if (error) - return error; + return fz_rethrow(error, "cannot open encryption stream"); } else { @@ -33,23 +35,26 @@ writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen error = pdf_openrawstream(&srcstm, xref, oid, gen); if (error) + { + error = fz_rethrow(error, "cannot open raw stream"); goto cleanupdst; + } while (1) { - n = fz_read(srcstm, buf, sizeof buf); - if (n == 0) - break; - if (n < 0) + error = fz_read(&n, srcstm, buf, sizeof buf); + if (error) { - error = fz_ioerror(srcstm); + error = fz_rethrow(error, "cannot read stream"); goto cleanupsrc; } + if (n == 0) + break; - n = fz_write(dststm, buf, n); - if (n < 0) + error = fz_write(dststm, buf, n); + if (error) { - error = fz_ioerror(dststm); + error = fz_rethrow(error, "cannot write stream"); goto cleanupsrc; } } @@ -59,7 +64,7 @@ writestream(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen fz_print(out, "endstream\n"); - return nil; + return fz_okay; cleanupsrc: fz_dropstream(srcstm); @@ -76,7 +81,7 @@ writeobject(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen error = pdf_cacheobject(xref, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot load object"); if (encrypt) pdf_cryptobj(encrypt, x->obj, oid, gen); @@ -92,12 +97,12 @@ writeobject(fz_stream *out, pdf_xref *xref, pdf_crypt *encrypt, int oid, int gen { error = writestream(out, xref, encrypt, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot write stream"); } fz_print(out, "endobj\n\n"); - return nil; + return fz_okay; } static int countmodified(pdf_xref *xref, int oid) @@ -123,7 +128,7 @@ pdf_updatexref(pdf_xref *xref, char *path) error = fz_openafile(&out, path); if (error) - return error; + return fz_rethrow(error, "cannot open output file"); fz_print(out, "\n"); @@ -134,7 +139,10 @@ pdf_updatexref(pdf_xref *xref, char *path) xref->table[oid].ofs = fz_tell(out); error = writeobject(out, xref, xref->crypt, oid, xref->table[oid].gen); if (error) + { + error = fz_rethrow(error, "cannot write object (oid=%d)", oid); goto cleanup; + } } } @@ -161,9 +169,9 @@ pdf_updatexref(pdf_xref *xref, char *path) xref->table[oid + i].type = 'n'; fz_print(out, "%010d %05d %c \n", - xref->table[oid + i].ofs, - xref->table[oid + i].gen, - xref->table[oid + i].type); + xref->table[oid + i].ofs, + xref->table[oid + i].gen, + xref->table[oid + i].type); } oid += n; @@ -205,7 +213,7 @@ pdf_updatexref(pdf_xref *xref, char *path) xref->startxref = startxref; fz_dropstream(out); - return nil; + return fz_okay; cleanup: fz_dropstream(out); @@ -232,27 +240,27 @@ pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt) error = pdf_allocobject(xref, &eoid, &egen); if (error) - return error; + return fz_rethrow(error, "cannot allocate encryption object"); pdf_cryptobj(encrypt, encrypt->encrypt, eoid, egen); error = pdf_updateobject(xref, eoid, egen, encrypt->encrypt); if (error) - return error; + return fz_rethrow(error, "cannot update encryption object"); } ofsbuf = fz_malloc(sizeof(int) * xref->len); if (!ofsbuf) - return fz_outofmem; + return fz_throw("outofmem: offset buffer"); error = fz_openwfile(&out, path); if (error) { fz_free(ofsbuf); - return error; + return fz_rethrow(error, "cannot open output file"); } - fz_print(out, "%%PDF-%1.1f\n", xref->version); + fz_print(out, "%%PDF-%d.%df\n", xref->version / 10, xref->version % 10); fz_print(out, "%%\342\343\317\323\n\n"); for (oid = 0; oid < xref->len; oid++) @@ -263,7 +271,10 @@ pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt) ofsbuf[oid] = fz_tell(out); error = writeobject(out, xref, encrypt, oid, x->type == 'o' ? 0 : x->gen); if (error) + { + error = fz_rethrow(error, "cannot write object (oid=%d)", oid); goto cleanup; + } } else { @@ -316,10 +327,10 @@ pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt) if(ofsbuf) fz_free(ofsbuf); fz_dropstream(out); - return nil; + return fz_okay; cleanup: - if(ofsbuf) fz_free(ofsbuf); + if (ofsbuf) fz_free(ofsbuf); fz_dropstream(out); return error; } diff --git a/mupdf/pdf_shade.c b/mupdf/pdf_shade.c index 7da1824a..da185a8c 100644 --- a/mupdf/pdf_shade.c +++ b/mupdf/pdf_shade.c @@ -107,8 +107,8 @@ loadshadedict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_m { shade->bbox = pdf_torect(obj); pdf_logshade("bbox [%g %g %g %g]\n", - shade->bbox.x0, shade->bbox.y0, - shade->bbox.x1, shade->bbox.y1); + shade->bbox.x0, shade->bbox.y0, + shade->bbox.x1, shade->bbox.y1); } switch(type) @@ -179,7 +179,7 @@ pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_obj *ref) { mat = pdf_tomatrix(obj); pdf_logshade("matrix [%g %g %g %g %g %g]\n", - mat.a, mat.b, mat.c, mat.d, mat.e, mat.f); + mat.a, mat.b, mat.c, mat.d, mat.e, mat.f); } else { diff --git a/mupdf/pdf_shade1.c b/mupdf/pdf_shade1.c index 837a499e..217284ca 100644 --- a/mupdf/pdf_shade1.c +++ b/mupdf/pdf_shade1.c @@ -20,6 +20,7 @@ pdf_loadtype1shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, fz_obj *ref) float x, y; float xn, yn; float x0, y0, x1, y1; + float t; int n; pdf_logshade("load type1 shade {\n"); diff --git a/mupdf/pdf_store.c b/mupdf/pdf_store.c index f632657f..71978292 100644 --- a/mupdf/pdf_store.c +++ b/mupdf/pdf_store.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" typedef struct pdf_item_s pdf_item; @@ -32,19 +32,19 @@ pdf_newstore(pdf_store **storep) store = fz_malloc(sizeof(pdf_store)); if (!store) - return fz_outofmem; + return fz_throw("outofmem: store struct");; error = fz_newhash(&store->hash, 4096, sizeof(struct refkey)); if (error) { fz_free(store); - return error; + return fz_rethrow(error, "cannot create hash"); } store->root = nil; *storep = store; - return nil; + return fz_okay; } static void dropitem(pdf_itemkind kind, void *val) @@ -78,6 +78,7 @@ pdf_emptystore(pdf_store *store) if (val) dropitem(key->kind, val); } + fz_emptyhash(store->hash); for (item = store->root; item; item = next) @@ -104,18 +105,6 @@ pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) { fz_error *error; - switch (kind) - { - case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; - case PDF_KFUNCTION: pdf_keepfunction(val); break; - case PDF_KXOBJECT: pdf_keepxobject(val); break; - case PDF_KIMAGE: fz_keepimage(val); break; - case PDF_KPATTERN: pdf_keeppattern(val); break; - case PDF_KSHADE: fz_keepshade(val); break; - case PDF_KCMAP: pdf_keepcmap(val); break; - case PDF_KFONT: fz_keepfont(val); break; - } - if (fz_isindirect(key)) { struct refkey item; @@ -128,7 +117,7 @@ pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) error = fz_hashinsert(store->hash, &item, val); if (error) - return error; + return fz_rethrow(error, "cannot insert object into hash"); } else @@ -137,7 +126,7 @@ pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) item = fz_malloc(sizeof(pdf_item)); if (!item) - return fz_outofmem; + return fz_throw("outofmem: store list node"); pdf_logrsrc("store item %d: ... = %p\n", kind, val); @@ -149,7 +138,19 @@ pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) store->root = item; } - return nil; + switch (kind) + { + case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; + case PDF_KFUNCTION: pdf_keepfunction(val); break; + case PDF_KXOBJECT: pdf_keepxobject(val); break; + case PDF_KIMAGE: fz_keepimage(val); break; + case PDF_KPATTERN: pdf_keeppattern(val); break; + case PDF_KSHADE: fz_keepshade(val); break; + case PDF_KCMAP: pdf_keepcmap(val); break; + case PDF_KFONT: fz_keepfont(val); break; + } + + return fz_okay; } void * diff --git a/mupdf/pdf_stream.c b/mupdf/pdf_stream.c index b1570c17..a6cf696c 100644 --- a/mupdf/pdf_stream.c +++ b/mupdf/pdf_stream.c @@ -13,7 +13,8 @@ pdf_isstream(pdf_xref *xref, int oid, int gen) return 0; error = pdf_cacheobject(xref, oid, gen); - if (error) { + if (error) + { fz_warn("%s", error->msg); fz_droperror(error); return 0; @@ -36,21 +37,21 @@ buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p) s = fz_toname(f); if (!strcmp(s, "ASCIIHexDecode") || !strcmp(s, "AHx")) - return fz_newahxd(fp, p); + error = fz_newahxd(fp, p); - if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85")) - return fz_newa85d(fp, p); + else if (!strcmp(s, "ASCII85Decode") || !strcmp(s, "A85")) + error = fz_newa85d(fp, p); - if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) - return fz_newfaxd(fp, p); + else if (!strcmp(s, "CCITTFaxDecode") || !strcmp(s, "CCF")) + error = fz_newfaxd(fp, p); - if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) - return fz_newdctd(fp, p); + else if (!strcmp(s, "DCTDecode") || !strcmp(s, "DCT")) + error = fz_newdctd(fp, p); - if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) - return fz_newrld(fp, p); + else if (!strcmp(s, "RunLengthDecode") || !strcmp(s, "RL")) + error = fz_newrld(fp, p); - if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) + else if (!strcmp(s, "FlateDecode") || !strcmp(s, "Fl")) { if (fz_isdict(p)) { @@ -59,25 +60,27 @@ buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p) { error = fz_newflated(&decompress, p); if (error) - return error; + return fz_rethrow(error, "cannot create deflate filter"); error = fz_newpredictd(&predict, p); if (error) { fz_dropfilter(decompress); - return error; + return fz_rethrow(error, "cannot create predictor filter"); } error = fz_newpipeline(fp, decompress, predict); fz_dropfilter(decompress); fz_dropfilter(predict); - return error; + if (error) + return fz_rethrow(error, "cannot create pipeline filter"); + return fz_okay; } } - return fz_newflated(fp, p); + error = fz_newflated(fp, p); } - if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) + else if (!strcmp(s, "LZWDecode") || !strcmp(s, "LZW")) { if (fz_isdict(p)) { @@ -86,38 +89,47 @@ buildonefilter(fz_filter **fp, fz_obj *f, fz_obj *p) { error = fz_newlzwd(&decompress, p); if (error) - return error; + return fz_rethrow(error, "cannot create lzwd filter"); error = fz_newpredictd(&predict, p); if (error) { fz_dropfilter(decompress); - return error; + return fz_rethrow(error, "cannot create predictor filter"); } error = fz_newpipeline(fp, decompress, predict); fz_dropfilter(decompress); fz_dropfilter(predict); - return error; + if (error) + return fz_rethrow(error, "cannot create pipeline filter"); + return fz_okay; } } - return fz_newlzwd(fp, p); + error = fz_newlzwd(fp, p); } #ifdef HAVE_JBIG2DEC - if (!strcmp(s, "JBIG2Decode")) + else if (!strcmp(s, "JBIG2Decode")) { /* TODO: extract and feed JBIG2Global */ - return fz_newjbig2d(fp, p); + error = fz_newjbig2d(fp, p); } #endif #ifdef HAVE_JASPER - if (!strcmp(s, "JPXDecode")) - return fz_newjpxd(fp, p); + else if (!strcmp(s, "JPXDecode")) + error = fz_newjpxd(fp, p); #endif - return fz_throw("syntaxerror: unknown filter: %s", s); + else + { + return fz_throw("unknown filter name (%s)", s); + } + + if (error) + return fz_rethrow(error, "cannot create filter"); + return fz_okay; } /* @@ -145,7 +157,7 @@ buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) error = buildonefilter(&tail, f, p); if (error) - return error; + return fz_rethrow(error, "cannot create filter"); if (head) { @@ -155,7 +167,7 @@ buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) if (error) { fz_dropfilter(newhead); - return error; + return fz_rethrow(error, "cannot create pipeline filter"); } head = newhead; } @@ -164,7 +176,7 @@ buildfilterchain(fz_filter **filterp, fz_filter *head, fz_obj *fs, fz_obj *ps) } *filterp = head; - return nil; + return fz_okay; } /* @@ -183,13 +195,13 @@ buildrawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int stmlen = fz_dictgets(stmobj, "Length"); error = pdf_resolve(&stmlen, xref); if (error) - return error; + return fz_rethrow(error, "cannot resolve stream /Length"); len = fz_toint(stmlen); fz_dropobj(stmlen); error = fz_newnullfilter(&base, len); if (error) - return error; + return fz_rethrow(error, "cannot create null filter"); if (xref->crypt) { @@ -200,14 +212,14 @@ buildrawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int if (error) { fz_dropfilter(base); - return error; + return fz_rethrow(error, "cannot create decryption filter"); } error = fz_newpipeline(&pipe, base, crypt); fz_dropfilter(base); fz_dropfilter(crypt); if (error) - return error; + return fz_rethrow(error, "cannot create pipeline filter"); *filterp = pipe; } @@ -216,7 +228,7 @@ buildrawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int *filterp = base; } - return nil; + return fz_okay; } /* @@ -226,25 +238,26 @@ buildrawfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, int fz_error * pdf_buildinlinefilter(fz_filter **filterp, fz_obj *stmobj) { + fz_error *error; fz_obj *filters; fz_obj *params; filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); - *filterp = nil; - if (filters) { if (fz_isname(filters)) - return buildonefilter(filterp, filters, params); - else if (fz_arraylen(filters) > 0) - return buildfilterchain(filterp, nil, filters, params); + error = buildonefilter(filterp, filters, params); + else + error = buildfilterchain(filterp, nil, filters, params); } + else + error = fz_newnullfilter(filterp, -1); - /* uh oh, no filter */ - - return nil; + if (error) + return fz_rethrow(error, "cannot create inline filter chain"); + return fz_okay; } /* @@ -261,7 +274,7 @@ pdf_buildfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, in error = buildrawfilter(&base, xref, stmobj, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot create raw filter chain"); filters = fz_dictgetsa(stmobj, "Filter", "F"); params = fz_dictgetsa(stmobj, "DecodeParms", "DP"); @@ -270,31 +283,46 @@ pdf_buildfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, in { error = pdf_resolve(&filters, xref); if (error) + { + error = fz_rethrow(error, "cannot resolve stream /Filter"); goto cleanup0; + } if (params) { error = pdf_resolve(¶ms, xref); if (error) + { + error = fz_rethrow(error, "cannot resolve stream /DecodeParms"); goto cleanup1; + } } if (fz_isname(filters)) { error = buildonefilter(&tmp, filters, params); if (error) + { + error = fz_rethrow(error, "cannot create filter"); goto cleanup2; + } error = fz_newpipeline(&pipe, base, tmp); fz_dropfilter(tmp); if (error) + { + error = fz_rethrow(error, "cannot create filter pipeline"); goto cleanup2; + } } else { error = buildfilterchain(&pipe, base, filters, params); if (error) + { + error = fz_rethrow(error, "cannot create filter chain"); goto cleanup2; + } } if (params) @@ -309,7 +337,7 @@ pdf_buildfilter(fz_filter **filterp, pdf_xref *xref, fz_obj *stmobj, int oid, in *filterp = base; } - return nil; + return fz_okay; cleanup2: if (params) @@ -322,7 +350,7 @@ cleanup0: } /* - * Open a stream for reading the raw (compressed but decrypted) data. + * Open a stream for reading the raw (compressed but decrypted) data. * Using xref->file while this is open is a bad idea. */ fz_error * @@ -331,33 +359,35 @@ pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen) pdf_xrefentry *x; fz_error *error; fz_filter *filter; - int n; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object id out of range"); + return fz_throw("object id out of range (%d)", oid); x = xref->table + oid; error = pdf_cacheobject(xref, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot load stream object (%d)", oid); if (x->stmbuf) { - return fz_openrbuffer(stmp, x->stmbuf); + error = fz_openrbuffer(stmp, x->stmbuf); + if (error) + return fz_rethrow(error, "cannot open stream from buffer"); + return fz_okay; } if (x->stmofs) { error = buildrawfilter(&filter, xref, x->obj, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot create raw filter"); - n = fz_seek(xref->file, x->stmofs, 0); - if (n == -1) + error = fz_seek(xref->file, x->stmofs, 0); + if (error) { fz_dropfilter(filter); - return fz_ioerror(xref->file); + return fz_rethrow(error, "cannot seek to stream"); } error = fz_openrfilter(stmp, filter, xref->file); @@ -365,16 +395,16 @@ pdf_openrawstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen) fz_dropfilter(filter); if (error) - return error; + return fz_rethrow(error, "cannot open filter stream"); - return nil; + return fz_okay; } - return fz_throw("syntaxerror: object is not a stream"); + return fz_throw("object is not a stream"); } /* - * Open a stream for reading uncompressed data. + * Open a stream for reading uncompressed data. * Put the opened file in xref->stream. * Using xref->file while a stream is open is a Bad idea. */ @@ -385,58 +415,59 @@ pdf_openstream(fz_stream **stmp, pdf_xref *xref, int oid, int gen) fz_error *error; fz_stream *rawstm; fz_filter *filter; - int n; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object id out of range"); + return fz_throw("object id out of range (%d)", oid); x = xref->table + oid; error = pdf_cacheobject(xref, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot load stream object (%d)", oid); if (x->stmbuf) { error = pdf_buildfilter(&filter, xref, x->obj, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot create filter"); error = fz_openrbuffer(&rawstm, x->stmbuf); if (error) { fz_dropfilter(filter); - return error; + return fz_rethrow(error, "cannot open stream from buffer"); } error = fz_openrfilter(stmp, filter, rawstm); fz_dropfilter(filter); fz_dropstream(rawstm); - return error; + if (error) + return fz_rethrow(error, "cannot open filter stream"); + return fz_okay; } if (x->stmofs) { error = pdf_buildfilter(&filter, xref, x->obj, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot create filter"); - n = fz_seek(xref->file, x->stmofs, 0); - if (n == -1) + error = fz_seek(xref->file, x->stmofs, 0); + if (error) { fz_dropfilter(filter); - return fz_ioerror(xref->file); + return fz_rethrow(error, "cannot seek to stream"); } error = fz_openrfilter(stmp, filter, xref->file); fz_dropfilter(filter); if (error) - return error; + return fz_rethrow(error, "cannot open filter stream"); - return nil; + return fz_okay; } - return fz_throw("syntaxerror: object is not a stream"); + return fz_throw("object is not a stream"); } /* @@ -447,21 +478,16 @@ pdf_loadrawstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen) { fz_error *error; fz_stream *stm; - int n; error = pdf_openrawstream(&stm, xref, oid, gen); if (error) - return error; - - n = fz_readall(bufp, stm); - if (n < 0) - error = fz_ioerror(stm); - else - error = nil; + return fz_rethrow(error, "cannot open raw stream (%d)", oid); + error = fz_readall(bufp, stm); fz_dropstream(stm); - - return error; + if (error) + return fz_rethrow(error, "cannot load stream into buffer (%d)", oid); + return fz_okay; } /* @@ -472,20 +498,15 @@ pdf_loadstream(fz_buffer **bufp, pdf_xref *xref, int oid, int gen) { fz_error *error; fz_stream *stm; - int n; error = pdf_openstream(&stm, xref, oid, gen); if (error) - return error; - - n = fz_readall(bufp, stm); - if (n < 0) - error = fz_ioerror(stm); - else - error = nil; + return fz_rethrow(error, "cannot open stream (%d)", oid); + error = fz_readall(bufp, stm); fz_dropstream(stm); - - return error; + if (error) + return fz_rethrow(error, "cannot load stream into buffer (%d)", oid); + return fz_okay; } diff --git a/mupdf/pdf_type3.c b/mupdf/pdf_type3.c index b19a7308..27ecfa3a 100644 --- a/mupdf/pdf_type3.c +++ b/mupdf/pdf_type3.c @@ -1,5 +1,7 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" + +/* TODO: we leak the pixmap buffer. not good. we should render into the glyph cache directly or keep it in the font struct.. */ #define GCMEM (4 * 1024) @@ -29,14 +31,14 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) fz_irect bbox; if (cid < 0 || cid > 255) - return fz_throw("rangecheck: glyph out of range"); + return fz_throw("assert: glyph out of range"); tree = font->charprocs[cid]; if (!tree) { glyph->w = 0; glyph->h = 0; - return nil; + return fz_okay; } ctm = fz_concat(font->matrix, trm); @@ -69,21 +71,30 @@ loadcharproc(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) fz_stream *stm; error = pdf_newcsi(&csi, 1); + if (error) + return fz_rethrow(error, "cannot create interpreter"); error = pdf_openstream(&stm, xref, fz_tonum(stmref), fz_togen(stmref)); if (error) - return error; + { + pdf_dropcsi(csi); + return fz_rethrow(error, "cannot open glyph content stream"); + } error = pdf_runcsi(csi, xref, rdb, stm); - - fz_dropstream(stm); + if (error) + { + fz_dropstream(stm); + pdf_dropcsi(csi); + return fz_rethrow(error, "cannot interpret glyph content stream"); + } *treep = csi->tree; csi->tree = nil; + fz_dropstream(stm); pdf_dropcsi(csi); - - return error; + return fz_okay; } fz_error * @@ -110,7 +121,7 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) font = pdf_newfont(buf); if (!font) - return fz_outofmem; + return fz_throw("outofmem: font struct"); pdf_logfont("load type3 font %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), font); pdf_logfont("name %s\n", buf); @@ -122,16 +133,16 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) font->matrix = pdf_tomatrix(obj); pdf_logfont("matrix [%g %g %g %g %g %g]\n", - font->matrix.a, font->matrix.b, - font->matrix.c, font->matrix.d, - font->matrix.e, font->matrix.f); + font->matrix.a, font->matrix.b, + font->matrix.c, font->matrix.d, + font->matrix.e, font->matrix.f); obj = fz_dictgets(dict, "FontBBox"); bbox = pdf_torect(obj); pdf_logfont("bbox [%g %g %g %g]\n", - bbox.x0, bbox.y0, - bbox.x1, bbox.y1); + bbox.x0, bbox.y0, + bbox.x1, bbox.y1); bbox = fz_transformaabb(font->matrix, bbox); bbox.x0 = fz_floor(bbox.x0 * 1000); @@ -193,7 +204,7 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) goto cleanup; error = pdf_loadtounicode(font, xref, - estrings, nil, fz_dictgets(dict, "ToUnicode")); + estrings, nil, fz_dictgets(dict, "ToUnicode")); if (error) goto cleanup; diff --git a/mupdf/pdf_xobject.c b/mupdf/pdf_xobject.c index 0819f04b..54062351 100644 --- a/mupdf/pdf_xobject.c +++ b/mupdf/pdf_xobject.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" fz_error * pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) @@ -11,12 +11,12 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if ((*formp = pdf_finditem(xref->store, PDF_KXOBJECT, ref))) { pdf_keepxobject(*formp); - return nil; + return fz_okay; } form = fz_malloc(sizeof(pdf_xobject)); if (!form) - return fz_outofmem; + return fz_throw("outofmem: xobject struct"); form->refs = 1; form->resources = nil; @@ -28,8 +28,8 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) form->bbox = pdf_torect(obj); pdf_logrsrc("bbox [%g %g %g %g]\n", - form->bbox.x0, form->bbox.y0, - form->bbox.x1, form->bbox.y1); + form->bbox.x0, form->bbox.y0, + form->bbox.x1, form->bbox.y1); obj = fz_dictgets(dict, "Matrix"); if (obj) @@ -38,9 +38,9 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) form->matrix = fz_identity(); pdf_logrsrc("matrix [%g %g %g %g %g %g]\n", - form->matrix.a, form->matrix.b, - form->matrix.c, form->matrix.d, - form->matrix.e, form->matrix.f); + form->matrix.a, form->matrix.b, + form->matrix.c, form->matrix.d, + form->matrix.e, form->matrix.f); obj = fz_dictgets(dict, "Resources"); if (obj) @@ -49,14 +49,14 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if (error) { pdf_dropxobject(form); - return error; + return fz_rethrow(error, "cannot resolve xobject resources"); } error = pdf_loadresources(&form->resources, xref, obj); fz_dropobj(obj); if (error) { pdf_dropxobject(form); - return error; + return fz_rethrow(error, "cannot load xobject resources"); } } @@ -64,7 +64,7 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if (error) { pdf_dropxobject(form); - return error; + return fz_rethrow(error, "cannot load xobject content stream"); } pdf_logrsrc("stream %d bytes\n", form->contents->wp - form->contents->rp); @@ -75,7 +75,7 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if (error) { pdf_dropxobject(form); - return error; + return fz_rethrow(error, "cannot store xobject resource"); } *formp = form; diff --git a/mupdf/pdf_xref.c b/mupdf/pdf_xref.c index cd787ff8..c9245bf0 100644 --- a/mupdf/pdf_xref.c +++ b/mupdf/pdf_xref.c @@ -1,5 +1,5 @@ -#include <fitz.h> -#include <mupdf.h> +#include "fitz.h" +#include "mupdf.h" /* * create xref structure. @@ -13,13 +13,14 @@ pdf_newxref(pdf_xref **xrefp) xref = fz_malloc(sizeof(pdf_xref)); if (!xref) - return fz_outofmem; + return fz_throw("outofmem: xref struct"); + memset(xref, 0, sizeof(pdf_xref)); pdf_logxref("newxref %p\n", xref); xref->file = nil; - xref->version = 1.3; + xref->version = 13; xref->startxref = 0; xref->crypt = nil; @@ -36,7 +37,7 @@ pdf_newxref(pdf_xref **xrefp) xref->store = nil; /* you need to create this if you want to render */ *xrefp = xref; - return nil; + return fz_okay; } void @@ -44,6 +45,7 @@ pdf_closexref(pdf_xref *xref) { pdf_logxref("closexref %p\n", xref); + /* don't touch the pdf_store module ... we don't want that dependency here */ if (xref->store) fz_warn("someone forgot to empty the store before freeing xref!"); @@ -73,7 +75,7 @@ pdf_initxref(pdf_xref *xref) { xref->table = fz_malloc(sizeof(pdf_xrefentry) * 128); if (!xref->table) - return fz_outofmem; + return fz_throw("outofmem: xref table"); xref->cap = 128; xref->len = 1; @@ -86,7 +88,7 @@ pdf_initxref(pdf_xref *xref) xref->table[0].stmofs = 0; xref->table[0].obj = nil; - return nil; + return fz_okay; } void @@ -135,12 +137,12 @@ pdf_debugxref(pdf_xref *xref) for (i = 0; i < xref->len; i++) { printf("%010d %05d %c | %d %c%c\n", - xref->table[i].ofs, - xref->table[i].gen, - xref->table[i].type, - xref->table[i].obj ? xref->table[i].obj->refs : 0, - xref->table[i].stmofs ? 'f' : '-', - xref->table[i].stmbuf ? 'b' : '-'); + xref->table[i].ofs, + xref->table[i].gen, + xref->table[i].type, + xref->table[i].obj ? xref->table[i].obj->refs : 0, + xref->table[i].stmofs ? 'f' : '-', + xref->table[i].stmbuf ? 'b' : '-'); } } @@ -171,16 +173,17 @@ pdf_decryptxref(pdf_xref *xref) if (error) { fz_dropobj(encrypt); - return error; + return fz_rethrow(error, "cannot resolve /ID object"); } error = pdf_newdecrypt(&xref->crypt, encrypt, id); fz_dropobj(encrypt); fz_dropobj(id); - return error; + if (error) + return fz_rethrow(error, "cannot create decrypter"); } - return nil; + return fz_okay; } /* @@ -252,7 +255,7 @@ pdf_allocobject(pdf_xref *xref, int *oidp, int *genp) newtable = fz_realloc(xref->table, sizeof(pdf_xrefentry) * newcap); if (!newtable) - return fz_outofmem; + return fz_throw("outofmem: xref table resize"); xref->table = newtable; xref->cap = newcap; @@ -278,7 +281,7 @@ pdf_allocobject(pdf_xref *xref, int *oidp, int *genp) xref->table[prev].type = 'd'; xref->table[prev].ofs = next; - return nil; + return fz_okay; } fz_error * @@ -288,7 +291,7 @@ pdf_deleteobject(pdf_xref *xref, int oid, int gen) int prev; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object number out of range: %d", oid); + return fz_throw("assert: object out of range: %d", oid); pdf_logxref("deleteobj %d %d\n", oid, gen); @@ -310,7 +313,7 @@ pdf_deleteobject(pdf_xref *xref, int oid, int gen) xref->table[prev].type = 'd'; xref->table[prev].ofs = oid; - return nil; + return fz_okay; } fz_error * @@ -319,7 +322,7 @@ pdf_updateobject(pdf_xref *xref, int oid, int gen, fz_obj *obj) pdf_xrefentry *x; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object number out of range: %d", oid); + return fz_throw("assert: object out of range: %d", oid); pdf_logxref("updateobj %d %d (%p)\n", oid, gen, obj); @@ -339,7 +342,7 @@ pdf_updateobject(pdf_xref *xref, int oid, int gen, fz_obj *obj) x->type = 'a'; - return nil; + return fz_okay; } fz_error * @@ -348,7 +351,7 @@ pdf_updatestream(pdf_xref *xref, int oid, int gen, fz_buffer *stm) pdf_xrefentry *x; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object number out of range: %d", oid); + return fz_throw("assert: object out of range: %d", oid); pdf_logxref("updatestm %d %d (%p)\n", oid, gen, stm); @@ -358,7 +361,7 @@ pdf_updatestream(pdf_xref *xref, int oid, int gen, fz_buffer *stm) fz_dropbuffer(x->stmbuf); x->stmbuf = fz_keepbuffer(stm); - return nil; + return fz_okay; } /* @@ -373,10 +376,9 @@ pdf_cacheobject(pdf_xref *xref, int oid, int gen) fz_error *error; pdf_xrefentry *x; int roid, rgen; - int n; if (oid < 0 || oid >= xref->len) - return fz_throw("rangecheck: object number out of range: %d", oid); + return fz_throw("object out of range: %d", oid); x = &xref->table[oid]; @@ -387,22 +389,22 @@ pdf_cacheobject(pdf_xref *xref, int oid, int gen) { error = fz_newnull(&x->obj); if (error) - return error; - return nil; + return fz_rethrow(error, "cannot create null for empty object slot"); + return fz_okay; } if (x->type == 'n') { - n = fz_seek(xref->file, x->ofs, 0); - if (n < 0) - return fz_ioerror(xref->file); + error = fz_seek(xref->file, x->ofs, 0); + if (error) + return fz_rethrow(error, "cannot seek to object %d (ofs=%d)", oid, x->ofs); error = pdf_parseindobj(&x->obj, xref->file, buf, sizeof buf, &roid, &rgen, &x->stmofs); if (error) - return error; + return fz_rethrow(error, "cannot parse object %d", oid);; if (roid != oid || rgen != gen) - return fz_throw("syntaxerror: found wrong object"); + return fz_throw("found object %d instead of %d", roid, oid); if (xref->crypt) pdf_cryptobj(xref->crypt, x->obj, oid, gen); @@ -414,11 +416,11 @@ pdf_cacheobject(pdf_xref *xref, int oid, int gen) { error = pdf_loadobjstm(xref, x->ofs, 0, buf, sizeof buf); if (error) - return error; + return fz_rethrow(error, "cannot load object stream containing object %d", oid); } } - return nil; + return fz_okay; } fz_error * @@ -428,26 +430,42 @@ pdf_loadobject(fz_obj **objp, pdf_xref *xref, int oid, int gen) error = pdf_cacheobject(xref, oid, gen); if (error) - return error; + return fz_rethrow(error, "cannot load object %d into cache", oid); *objp = fz_keepobj(xref->table[oid].obj); - return nil; + return fz_okay; } fz_error * pdf_loadindirect(fz_obj **objp, pdf_xref *xref, fz_obj *ref) { - assert(ref != nil); - return pdf_loadobject(objp, xref, fz_tonum(ref), fz_togen(ref)); + fz_error *error; + + if (ref == nil) + return fz_throw("assert: dereference null indirect reference"); + + error = pdf_loadobject(objp, xref, fz_tonum(ref), fz_togen(ref)); + if (error) + return fz_rethrow(error, "cannot load indirect object %d", fz_tonum(ref)); + + return fz_okay; } fz_error * pdf_resolve(fz_obj **objp, pdf_xref *xref) { + fz_error *error; + if (fz_isindirect(*objp)) - return pdf_loadindirect(objp, xref, *objp); + { + error = pdf_loadindirect(objp, xref, *objp); + if (error) + return fz_rethrow(error, "cannot load indirect object %d", fz_tonum(*objp)); + return fz_okay; + } + fz_keepobj(*objp); - return nil; + return fz_okay; } diff --git a/stream/crypt_arc4.c b/stream/crypt_arc4.c index 0a5c942f..a1eef199 100644 --- a/stream/crypt_arc4.c +++ b/stream/crypt_arc4.c @@ -38,14 +38,16 @@ fz_arc4init(fz_arc4 *arc4, unsigned char *key, unsigned keylen) arc4->x = 0; arc4->y = 0; - for (counter = 0; counter < 256; counter++) { + for (counter = 0; counter < 256; counter++) + { state[counter] = counter; } keyindex = 0; stateindex = 0; - for (counter = 0; counter < 256; counter++) { + for (counter = 0; counter < 256; counter++) + { t = state[counter]; stateindex = (stateindex + key[keyindex] + t) & 0xff; u = state[stateindex]; @@ -53,7 +55,8 @@ fz_arc4init(fz_arc4 *arc4, unsigned char *key, unsigned keylen) state[stateindex] = t; state[counter] = u; - if (++keyindex >= keylen) { + if (++keyindex >= keylen) + { keyindex = 0; } } @@ -87,7 +90,8 @@ void fz_arc4encrypt(fz_arc4 *arc4, unsigned char *dest, unsigned char *src, unsigned len) { unsigned int i; - for (i = 0; i < len; i++) { + for (i = 0; i < len; i++) + { unsigned char x; x = fz_arc4next(arc4); dest[i] = src[i] ^ x; diff --git a/stream/crypt_md5.c b/stream/crypt_md5.c index cf20024b..7a600612 100644 --- a/stream/crypt_md5.c +++ b/stream/crypt_md5.c @@ -83,7 +83,8 @@ static void encode(unsigned char *output, unsigned long *input, unsigned len) { unsigned i, j; - for (i = 0, j = 0; j < len; i++, j += 4) { + for (i = 0, j = 0; j < len; i++, j += 4) + { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); @@ -95,7 +96,8 @@ static void decode(unsigned long *output, unsigned char *input, unsigned len) { unsigned i, j; - for (i = 0, j = 0; j < len; i++, j += 4) { + for (i = 0, j = 0; j < len; i++, j += 4) + { output[i] = ((unsigned long)input[j]) | (((unsigned long)input[j+1]) << 8) | (((unsigned long)input[j+2]) << 16) | @@ -225,7 +227,8 @@ void fz_md5update(fz_md5 *context, unsigned char *input, unsigned inlen) partlen = 64 - index; /* Transform as many times as possible. */ - if (inlen >= partlen) { + if (inlen >= partlen) + { memcpy(context->buffer + index, input, partlen); transform(context->state, context->buffer); @@ -234,7 +237,8 @@ void fz_md5update(fz_md5 *context, unsigned char *input, unsigned inlen) index = 0; } - else { + else + { i = 0; } diff --git a/stream/filt_a85d.c b/stream/filt_a85d.c index 3db4951a..5bbe68cb 100644 --- a/stream/filt_a85d.c +++ b/stream/filt_a85d.c @@ -26,7 +26,7 @@ fz_newa85d(fz_filter **fp, fz_obj *params) FZ_NEWFILTER(fz_a85d, f, a85d); f->word = 0; f->count = 0; - return nil; + return fz_okay; } void @@ -90,7 +90,7 @@ fz_processa85d(fz_filter *filter, fz_buffer *in, fz_buffer *out) c = *in->rp++; if (c != '>') { - return fz_throw("ioerror: bad eod marker in a85d"); + return fz_throw("bad eod marker in a85d"); } if (out->wp + f->count - 1 > out->ep) { @@ -102,7 +102,7 @@ fz_processa85d(fz_filter *filter, fz_buffer *in, fz_buffer *out) case 0: break; case 1: - return fz_throw("ioerror: partial final byte in a85d"); + return fz_throw("partial final byte in a85d"); case 2: f->word = f->word * (85L * 85 * 85) + 0xffffffL; goto o1; @@ -122,7 +122,7 @@ o1: *(out->wp+0) = f->word >> 24; } else if (!iswhite(c)) { - return fz_throw("ioerror: bad data in a85d: '%c'", c); + return fz_throw("bad data in a85d: '%c'", c); } } } diff --git a/stream/filt_a85e.c b/stream/filt_a85e.c index f7b5912d..a33ee7c5 100644 --- a/stream/filt_a85e.c +++ b/stream/filt_a85e.c @@ -14,7 +14,7 @@ fz_newa85e(fz_filter **fp, fz_obj *params) { FZ_NEWFILTER(fz_a85e, f, a85e); f->c = 0; - return nil; + return fz_okay; } void diff --git a/stream/filt_ahxd.c b/stream/filt_ahxd.c index f54670b2..d670a8d9 100644 --- a/stream/filt_ahxd.c +++ b/stream/filt_ahxd.c @@ -44,7 +44,7 @@ fz_newahxd(fz_filter **fp, fz_obj *params) FZ_NEWFILTER(fz_ahxd, f, ahxd); f->odd = 0; f->a = 0; - return nil; + return fz_okay; } void @@ -88,7 +88,7 @@ fz_processahxd(fz_filter *filter, fz_buffer *in, fz_buffer *out) } else if (!iswhite(c)) { - return fz_throw("ioerror: bad data in ahxd: '%c'", c); + return fz_throw("bad data in ahxd: '%c'", c); } } } diff --git a/stream/filt_ahxe.c b/stream/filt_ahxe.c index 12c8aad0..8a2e271b 100644 --- a/stream/filt_ahxe.c +++ b/stream/filt_ahxe.c @@ -16,7 +16,7 @@ fz_newahxe(fz_filter **fp, fz_obj *params) { FZ_NEWFILTER(fz_ahxe, f, ahxe); f->c = 0; - return nil; + return fz_okay; } void diff --git a/stream/filt_arc4.c b/stream/filt_arc4.c index 3b3c5957..af038599 100644 --- a/stream/filt_arc4.c +++ b/stream/filt_arc4.c @@ -14,7 +14,7 @@ fz_newarc4filter(fz_filter **fp, unsigned char *key, unsigned keylen) { FZ_NEWFILTER(fz_arc4c, f, arc4filter); fz_arc4init(&f->arc4, key, keylen); - return nil; + return fz_okay; } void diff --git a/stream/filt_dctc.h b/stream/filt_dctc.h index 8aa6aeb7..72f61ef2 100644 --- a/stream/filt_dctc.h +++ b/stream/filt_dctc.h @@ -27,7 +27,7 @@ static void myoutmess(j_common_ptr cinfo) struct myerrmgr *err = (struct myerrmgr *)cinfo->err; char msgbuf[JMSG_LENGTH_MAX]; err->super.format_message(cinfo, msgbuf); - fprintf(stderr, "ioerror: dct: %s", msgbuf); + fz_warn("jpeg error: %s", msgbuf); } static void myiniterr(struct myerrmgr *err) diff --git a/stream/filt_dctd.c b/stream/filt_dctd.c index 38ab3fbf..d8fd552f 100644 --- a/stream/filt_dctd.c +++ b/stream/filt_dctd.c @@ -72,7 +72,7 @@ fz_newdctd(fz_filter **fp, fz_obj *params) d->cinfo.err = (struct jpeg_error_mgr*) &d->err; if (setjmp(d->err.jb)) { - err = fz_throw("ioerror in dctd: %s", d->err.msg); + err = fz_throw("cannot decode jpeg: %s", d->err.msg); fz_free(d); return err; } @@ -96,7 +96,7 @@ fz_newdctd(fz_filter **fp, fz_obj *params) d->cinfo.dct_method = JDCT_FASTEST; d->cinfo.do_fancy_upsampling = FALSE; - return nil; + return fz_okay; } void @@ -104,7 +104,7 @@ fz_dropdctd(fz_filter *filter) { fz_dctd *d = (fz_dctd*)filter; if (setjmp(d->err.jb)) { - fprintf(stderr, "ioerror in dct: jpeg_destroy_decompress: %s", d->err.msg); + fz_warn("jpeg error: jpeg_destroy_decompress: %s", d->err.msg); return; } jpeg_destroy_decompress(&d->cinfo); @@ -137,8 +137,9 @@ fz_processdctd(fz_filter *filter, fz_buffer *in, fz_buffer *out) d->src.super.bytes_in_buffer = in->wp - in->rp; d->src.super.next_input_byte = in->rp; - if (setjmp(d->err.jb)) { - return fz_throw("ioerror in dctd: %s", d->err.msg); + if (setjmp(d->err.jb)) + { + return fz_throw("cannot decode jpeg: %s", d->err.msg); } switch (d->stage) diff --git a/stream/filt_dcte.c b/stream/filt_dcte.c index 06f3fcbe..3ce0f21d 100644 --- a/stream/filt_dcte.c +++ b/stream/filt_dcte.c @@ -41,23 +41,24 @@ fz_newdcte(fz_filter **fp, fz_obj *params) e->stage = 0; obj = fz_dictgets(params, "Columns"); - if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Columns parameter"); } + if (!obj) { fz_free(e); return fz_throw("missing Columns parameter"); } e->columns = fz_toint(obj); obj = fz_dictgets(params, "Rows"); - if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Rows parameter"); } + if (!obj) { fz_free(e); return fz_throw("missing Rows parameter"); } e->rows = fz_toint(obj); obj = fz_dictgets(params, "Colors"); - if (!obj) { fz_free(e); return fz_throw("ioerror in dcte: missing Colors parameter"); } + if (!obj) { fz_free(e); return fz_throw("missing Colors parameter"); } e->colors = fz_toint(obj); /* setup error callback first thing */ myiniterr(&e->err); e->cinfo.err = (struct jpeg_error_mgr*) &e->err; - if (setjmp(e->err.jb)) { - err = fz_throw("ioerror in dcte: %s", e->err.msg); + if (setjmp(e->err.jb)) + { + err = fz_throw("cannot encode jpeg: %s", e->err.msg); fz_free(e); return err; } @@ -119,7 +120,7 @@ fz_newdcte(fz_filter **fp, fz_obj *params) /* TODO: quant-tables and huffman-tables */ - return nil; + return fz_okay; } void @@ -128,7 +129,7 @@ fz_dropdcte(fz_filter *filter) fz_dcte *e = (fz_dcte*)filter; if (setjmp(e->err.jb)) { - fprintf(stderr, "ioerror in dcte: jpeg_destroy_compress: %s", e->err.msg); + fz_warn("jpeg error: jpeg_destroy_compress: %s", e->err.msg); return; } @@ -161,7 +162,7 @@ fz_setquanttables(fz_dcte *e, unsigned int **qtables, int qfactor) unsigned int table[64]; if (setjmp(e->err.jb)) { - return fz_throw("ioerror in dcte: %s", e->err.msg); + return fz_throw("jpeg error: jpeg_add_quant_table: %s", e->err.msg); } /* TODO: check for duplicate tables */ @@ -174,7 +175,7 @@ fz_setquanttables(fz_dcte *e, unsigned int **qtables, int qfactor) e->cinfo.comp_info[i].quant_tbl_no = i; } - return nil; + return fz_okay; } fz_error * @@ -189,8 +190,9 @@ fz_processdcte(fz_filter *filter, fz_buffer *in, fz_buffer *out) e->dst.super.free_in_buffer = out->ep - out->wp; e->dst.super.next_output_byte = out->wp; - if (setjmp(e->err.jb)) { - return fz_throw("ioerror in dcte: %s", e->err.msg); + if (setjmp(e->err.jb)) + { + return fz_throw("cannot encode jpeg: %s", e->err.msg); } switch (e->stage) diff --git a/stream/filt_faxd.c b/stream/filt_faxd.c index a0449078..4de4d226 100644 --- a/stream/filt_faxd.c +++ b/stream/filt_faxd.c @@ -90,15 +90,24 @@ fz_newfaxd(fz_filter **fp, fz_obj *params) fax->eolc = 0; fax->ref = fz_malloc(fax->stride); - if (!fax->ref) { fz_free(fax); return fz_outofmem; } + if (!fax->ref) + { + fz_free(fax); + return fz_throw("outofmem: scanline buffer one"); + } fax->dst = fz_malloc(fax->stride); - if (!fax->dst) { fz_free(fax); fz_free(fax->ref); return fz_outofmem; } + if (!fax->dst) + { + fz_free(fax); + fz_free(fax->ref); + return fz_throw("outofmem: scanline buffer two"); + } memset(fax->ref, 0, fax->stride); memset(fax->dst, 0, fax->stride); - return nil; + return fz_okay; } void @@ -125,7 +134,7 @@ static inline fz_error * fillbits(fz_faxd *fax, fz_buffer *in) fax->word |= *in->rp << fax->bidx; in->rp ++; } - return nil; + return fz_okay; } static int @@ -164,13 +173,13 @@ dec1d(fz_faxd *fax) code = getcode(fax, cf_white_decode, cfd_white_initial_bits); if (code == UNCOMPRESSED) - return fz_throw("ioerror: uncompressed data in faxd"); + return fz_throw("uncompressed data in faxd"); if (code < 0) - return fz_throw("ioerror: negative code in 1d faxd"); + return fz_throw("negative code in 1d faxd"); if (fax->a + code > fax->columns) - return fz_throw("ioerror: overflow in 1d faxd"); + return fz_throw("overflow in 1d faxd"); if (fax->c) setbits(fax->dst, fax->a, fax->a + code); @@ -185,7 +194,7 @@ dec1d(fz_faxd *fax) else fax->stage = SMAKEUP; - return nil; + return fz_okay; } /* decode one 2d code */ @@ -205,13 +214,13 @@ dec2d(fz_faxd *fax) code = getcode(fax, cf_white_decode, cfd_white_initial_bits); if (code == UNCOMPRESSED) - return fz_throw("ioerror: uncompressed data in faxd"); + return fz_throw("uncompressed data in faxd"); if (code < 0) - return fz_throw("ioerror: negative code in 2d faxd"); + return fz_throw("negative code in 2d faxd"); if (fax->a + code > fax->columns) - return fz_throw("ioerror: overflow in 2d faxd"); + return fz_throw("overflow in 2d faxd"); if (fax->c) setbits(fax->dst, fax->a, fax->a + code); @@ -227,7 +236,7 @@ dec2d(fz_faxd *fax) fax->stage = SNORMAL; } - return nil; + return fz_okay; } code = getcode(fax, cf_2d_decode, cfd_2d_initial_bits); @@ -295,13 +304,13 @@ dec2d(fz_faxd *fax) break; case UNCOMPRESSED: - return fz_throw("ioerror: uncompressed data in faxd"); + return fz_throw("uncompressed data in faxd"); case ERROR: - return fz_throw("ioerror: invalid code in 2d faxd"); + return fz_throw("invalid code in 2d faxd"); default: - return fz_throw("ioerror: invalid code in 2d faxd (%d)", code); + return fz_throw("invalid code in 2d faxd (%d)", code); } return 0; @@ -361,14 +370,14 @@ loop: { fax->eolc = 0; error = dec1d(fax); - if (error) return error; + if (error) return error; /* can be fz_io* or real error */ } else if (fax->dim == 2) { fax->eolc = 0; error = dec2d(fax); - if (error) return error; + if (error) return error; /* can be fz_io* or real error */ } /* no eol check after makeup codes nor in the middle of an H code */ diff --git a/stream/filt_faxe.c b/stream/filt_faxe.c index 811b5a29..39d46a8c 100644 --- a/stream/filt_faxe.c +++ b/stream/filt_faxe.c @@ -75,15 +75,24 @@ fz_newfaxe(fz_filter **fp, fz_obj *params) fax->c = 0; fax->ref = fz_malloc(fax->stride); - if (!fax->ref) { fz_free(fax); return fz_outofmem; } + if (!fax->ref) + { + fz_free(fax); + return fz_throw("outofmemory: scanline buffer one"); + } fax->src = fz_malloc(fax->stride); - if (!fax->src) { fz_free(fax); fz_free(fax->ref); return fz_outofmem; } + if (!fax->src) + { + fz_free(fax); + fz_free(fax->ref); + return fz_throw("outofmemory: scanline buffer two"); + } memset(fax->ref, 0, fax->stride); memset(fax->src, 0, fax->stride); - return nil; + return fz_okay; } void @@ -188,7 +197,7 @@ enc1d(fz_faxe *fax, unsigned char *line, fz_buffer *out) fax->c = !fax->c; } - return 0; + return fz_okay; } static fz_error * @@ -245,7 +254,7 @@ enc2d(fz_faxe *fax, unsigned char *ref, unsigned char *src, fz_buffer *out) } } - return 0; + return fz_okay; } static fz_error * @@ -349,7 +358,7 @@ process(fz_faxe *fax, fz_buffer *in, fz_buffer *out) } if (error) - return error; + return error; /* one of fz_io* */ fax->ridx ++; diff --git a/stream/filt_flate.c b/stream/filt_flate.c index 1e048c17..cd079cd2 100644 --- a/stream/filt_flate.c +++ b/stream/filt_flate.c @@ -52,12 +52,12 @@ fz_newflated(fz_filter **fp, fz_obj *params) if (ei != Z_OK) { - eo = fz_throw("ioerror: inflateInit: %s", f->z.msg); + eo = fz_throw("zlib error: inflateInit: %s", f->z.msg); fz_free(f); return eo; } - return nil; + return fz_okay; } void @@ -108,7 +108,7 @@ fz_processflated(fz_filter *f, fz_buffer *in, fz_buffer *out) } else { - return fz_throw("ioerror: inflate: %s", zp->msg); + return fz_throw("zlib error: inflate: %s", zp->msg); } } @@ -147,12 +147,12 @@ fz_newflatee(fz_filter **fp, fz_obj *params) if (ei != Z_OK) { - eo = fz_throw("ioerror: deflateInit: %s", f->z.msg); + eo = fz_throw("zlib error: deflateInit: %s", f->z.msg); fz_free(f); return eo; } - return nil; + return fz_okay; } void @@ -205,7 +205,7 @@ fz_processflatee(fz_filter *f, fz_buffer *in, fz_buffer *out) } else { - return fz_throw("ioerror: deflate: %s", zp->msg); + return fz_throw("zlib error: deflate: %s", zp->msg); } } diff --git a/stream/filt_jbig2d.c b/stream/filt_jbig2d.c index ce73ee53..17abecd4 100644 --- a/stream/filt_jbig2d.c +++ b/stream/filt_jbig2d.c @@ -48,7 +48,7 @@ fz_newjbig2d(fz_filter **fp, fz_obj *params) d->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, nil, nil, nil); d->page = nil; d->idx = 0; - return nil; + return fz_okay; } void @@ -65,7 +65,7 @@ fz_setjbig2dglobalstream(fz_filter *filter, unsigned char *buf, int len) jbig2_data_in(d->ctx, buf, len); d->gctx = jbig2_make_global_ctx(d->ctx); d->ctx = jbig2_ctx_new(nil, JBIG2_OPTIONS_EMBEDDED, d->gctx, nil, nil); - return nil; + return fz_okay; } fz_error * diff --git a/stream/filt_jpxd.c b/stream/filt_jpxd.c index 1b93f477..a8e14d0d 100644 --- a/stream/filt_jpxd.c +++ b/stream/filt_jpxd.c @@ -42,22 +42,24 @@ fz_newjpxd(fz_filter **fp, fz_obj *params) FZ_NEWFILTER(fz_jpxd, d, jpxd); err = jas_init(); - if (err) { + if (err) + { fz_free(d); - return fz_throw("ioerror in jpxd: jas_init()"); + return fz_throw("jasper error: jas_init()"); } d->stream = jas_stream_memopen(nil, 0); - if (!d->stream) { + if (!d->stream) + { fz_free(d); - return fz_throw("ioerror in jpxd: jas_stream_memopen()"); + return fz_throw("jasper error: jas_stream_memopen()"); } d->image = nil; d->offset = 0; d->stage = 0; - return nil; + return fz_okay; } void @@ -83,7 +85,8 @@ fz_processjpxd(fz_filter *filter, fz_buffer *in, fz_buffer *out) } input: - while (in->rp < in->wp) { + while (in->rp < in->wp) + { n = jas_stream_write(d->stream, in->rp, in->wp - in->rp); in->rp += n; } @@ -98,7 +101,7 @@ decode: d->image = jas_image_decode(d->stream, -1, 0); if (!d->image) - return fz_throw("ioerror in jpxd: unable to decode image data"); + return fz_throw("jasper error: jas_image_decode()"); fprintf(stderr, "P%c\n# JPX %d x %d n=%d bpc=%d colorspace=%04x %s\n%d %d\n%d\n", jas_image_numcmpts(d->image) == 1 ? '5' : '6', diff --git a/stream/filt_lzwd.c b/stream/filt_lzwd.c index bbdb4984..127ebde8 100644 --- a/stream/filt_lzwd.c +++ b/stream/filt_lzwd.c @@ -83,7 +83,7 @@ fz_newlzwd(fz_filter **fp, fz_obj *params) lzw->oldcode = -1; lzw->resume = 0; - return nil; + return fz_okay; } void @@ -107,7 +107,7 @@ static inline fz_error * fillbits(fz_lzwd *lzw, fz_buffer *in) lzw->word |= *in->rp << lzw->bidx; in->rp ++; } - return nil; + return fz_okay; } static inline void unstuff(fz_lzwd *lzw, fz_buffer *in) diff --git a/stream/filt_lzwe.c b/stream/filt_lzwe.c index 978b6ef2..ec6f5f7a 100644 --- a/stream/filt_lzwe.c +++ b/stream/filt_lzwe.c @@ -83,7 +83,7 @@ fz_newlzwe(fz_filter **fp, fz_obj *params) clearhash(lzw); - return nil; + return fz_okay; } void diff --git a/stream/filt_null.c b/stream/filt_null.c index f51039b4..601ed815 100644 --- a/stream/filt_null.c +++ b/stream/filt_null.c @@ -16,7 +16,7 @@ fz_newnullfilter(fz_filter **fp, int len) FZ_NEWFILTER(fz_nullfilter, f, nullfilter); f->len = len; f->cur = 0; - return nil; + return fz_okay; } void @@ -34,7 +34,8 @@ fz_processnullfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out) if (f->len >= 0) n = MIN(n, f->len - f->cur); - if (n) { + if (n) + { memcpy(out->wp, in->rp, n); in->rp += n; out->wp += n; @@ -48,6 +49,6 @@ fz_processnullfilter(fz_filter *filter, fz_buffer *in, fz_buffer *out) if (out->wp == out->ep) return fz_ioneedout; - return fz_throw("braindead programmer in nullfilter"); + return fz_throw("braindead programmer trapped in nullfilter"); } diff --git a/stream/filt_pipeline.c b/stream/filt_pipeline.c index 65e1c38d..ea0b9885 100644 --- a/stream/filt_pipeline.c +++ b/stream/filt_pipeline.c @@ -24,7 +24,7 @@ fz_chainpipeline(fz_filter **fp, fz_filter *head, fz_filter *tail, fz_buffer *bu p->tail = fz_keepfilter(tail); p->tailneedsin = 1; p->buffer = fz_keepbuffer(buf); - return nil; + return fz_okay; } void @@ -49,9 +49,13 @@ fz_newpipeline(fz_filter **fp, fz_filter *head, fz_filter *tail) p->tailneedsin = 1; error = fz_newbuffer(&p->buffer, FZ_BUFSIZE); - if (error) { fz_free(p); return error; } + if (error) + { + fz_free(p); + return fz_rethrow(error, "cannot create buffer"); + } - return nil; + return fz_okay; } void @@ -100,8 +104,11 @@ head: else if (e == fz_iodone) goto tail; + else if (e) + return fz_rethrow(e, "cannot process head filter"); + else - return e; + return fz_okay; tail: e = fz_process(p->tail, p->buffer, out); @@ -123,7 +130,10 @@ tail: else if (e == fz_iodone) return fz_iodone; + else if (e) + return fz_rethrow(e, "cannot process tail filter"); + else - return e; + return fz_okay; } diff --git a/stream/filt_predict.c b/stream/filt_predict.c index bf4680e7..4654e792 100644 --- a/stream/filt_predict.c +++ b/stream/filt_predict.c @@ -52,16 +52,22 @@ fz_newpredict(fz_filter **fp, fz_obj *params, int encode) p->stride = (p->bpc * p->colors * p->columns + 7) / 8; p->bpp = (p->bpc * p->colors + 7) / 8; - if (p->predictor >= 10) { + if (p->predictor >= 10) + { p->ref = fz_malloc(p->stride); - if (!p->ref) { fz_free(p); return fz_outofmem; } + if (!p->ref) + { + fz_free(p); + return fz_throw("outofmem: scanline buffer"); + } memset(p->ref, 0, p->stride); } - else { + else + { p->ref = nil; } - return nil; + return fz_okay; } void @@ -122,8 +128,10 @@ tiff(fz_predict *p, unsigned char *in, unsigned char *out) for (k = 0; k < p->colors; k++) left[k] = 0; - for (i = 0; i < p->columns; i++) { - for (k = 0; k < p->colors; k++) { + for (i = 0; i < p->columns; i++) + { + for (k = 0; k < p->colors; k++) + { int a = getcomponent(in, i * p->colors + k, p->bpc); int b = p->encode ? a - left[k] : a + left[k]; int c = b % (1 << p->bpc); @@ -138,7 +146,8 @@ png(fz_predict *p, unsigned char *in, unsigned char *out, int predictor) { int upleft[MAXC], left[MAXC], i, k; - for (k = 0; k < p->bpp; k++) { + for (k = 0; k < p->bpp; k++) + { left[k] = 0; upleft[k] = 0; } @@ -187,7 +196,8 @@ fz_processpredict(fz_filter *filter, fz_buffer *in, fz_buffer *out) while (1) { - if (in->rp + dec->stride + (!dec->encode && ispng) > in->wp) { + if (in->rp + dec->stride + (!dec->encode && ispng) > in->wp) + { if (in->eof) return fz_iodone; return fz_ioneedin; @@ -196,22 +206,27 @@ fz_processpredict(fz_filter *filter, fz_buffer *in, fz_buffer *out) if (out->wp + dec->stride + (dec->encode && ispng) > out->ep) return fz_ioneedout; - if (dec->predictor == 1) { + if (dec->predictor == 1) + { none(dec, in->rp, out->wp); } - else if (dec->predictor == 2) { + else if (dec->predictor == 2) + { if (dec->bpc != 8) memset(out->wp, 0, dec->stride); tiff(dec, in->rp, out->wp); } - else { - if (dec->encode) { + else + { + if (dec->encode) + { predictor = dec->predictor - 10; if (predictor < 0 || predictor > 4) predictor = 1; *out->wp ++ = predictor; } - else { + else + { predictor = *in->rp++; } png(dec, in->rp, out->wp, predictor); diff --git a/stream/filt_rld.c b/stream/filt_rld.c index dc720fbd..74499a57 100644 --- a/stream/filt_rld.c +++ b/stream/filt_rld.c @@ -5,7 +5,7 @@ fz_error * fz_newrld(fz_filter **fp, fz_obj *params) { FZ_NEWFILTER(fz_filter, f, rld); - return nil; + return fz_okay; } void diff --git a/stream/filt_rle.c b/stream/filt_rle.c index 6160e148..458bf3ba 100644 --- a/stream/filt_rle.c +++ b/stream/filt_rle.c @@ -42,7 +42,7 @@ fz_newrle(fz_filter **fp, fz_obj *params) enc->state = ZERO; enc->run = 0; - return nil; + return fz_okay; } void diff --git a/stream/obj_array.c b/stream/obj_array.c index cfcd3fb1..3953470a 100644 --- a/stream/obj_array.c +++ b/stream/obj_array.c @@ -10,7 +10,8 @@ fz_newarray(fz_obj **op, int initialcap) int i; obj = *op = fz_malloc(sizeof (fz_obj)); - if (!obj) return fz_outofmem; + if (!obj) + return fz_throw("outofmem: array struct"); obj->refs = 1; obj->kind = FZ_ARRAY; @@ -19,12 +20,16 @@ fz_newarray(fz_obj **op, int initialcap) obj->u.a.cap = initialcap > 0 ? initialcap : 6; obj->u.a.items = fz_malloc(sizeof (fz_obj*) * obj->u.a.cap); - if (!obj->u.a.items) { fz_free(obj); return fz_outofmem; } + if (!obj->u.a.items) + { + fz_free(obj); + return fz_throw("outofmem: array item buffer"); + } for (i = 0; i < obj->u.a.cap; i++) obj->u.a.items[i] = nil; - return nil; + return fz_okay; } fz_error * @@ -35,18 +40,25 @@ fz_copyarray(fz_obj **op, fz_obj *obj) int i; if (!fz_isarray(obj)) - return fz_throw("typecheck in copyarray"); + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); error = fz_newarray(&new, fz_arraylen(obj)); - if (error) return error; - *op = new; + if (error) + return fz_rethrow(error, "cannot create new array"); - for (i = 0; i < fz_arraylen(obj); i++) { + for (i = 0; i < fz_arraylen(obj); i++) + { error = fz_arraypush(new, fz_arrayget(obj, i)); - if (error) { fz_droparray(new); return error; } + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot add item to array"); + } } - return nil; + *op = new; + + return fz_okay; } fz_error * @@ -58,39 +70,69 @@ fz_deepcopyarray(fz_obj **op, fz_obj *obj) int i; if (!fz_isarray(obj)) - return fz_throw("typecheck in deepcopyarray"); + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); error = fz_newarray(&new, fz_arraylen(obj)); - if (error) return error; - *op = new; + if (error) + return fz_rethrow(error, "cannot create new array"); for (i = 0; i < fz_arraylen(obj); i++) { val = fz_arrayget(obj, i); - if (fz_isarray(val)) { + if (fz_isarray(val)) + { error = fz_deepcopyarray(&val, val); - if (error) { fz_droparray(new); return error; } + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot deep copy item"); + } + error = fz_arraypush(new, val); - if (error) { fz_dropobj(val); fz_droparray(new); return error; } + if (error) + { + fz_dropobj(val); + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } + fz_dropobj(val); } - else if (fz_isdict(val)) { + else if (fz_isdict(val)) + { error = fz_deepcopydict(&val, val); - if (error) { fz_droparray(new); return error; } + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot deep copy item"); + } + error = fz_arraypush(new, val); - if (error) { fz_dropobj(val); fz_droparray(new); return error; } + if (error) + { + fz_dropobj(val); + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } fz_dropobj(val); } - else { + else + { error = fz_arraypush(new, val); - if (error) { fz_droparray(new); return error; } + if (error) + { + fz_droparray(new); + return fz_rethrow(error, "cannot add copied item to array"); + } } } - return nil; + *op = new; + + return fz_okay; } int @@ -117,17 +159,17 @@ fz_error * fz_arrayput(fz_obj *obj, int i, fz_obj *item) { if (!fz_isarray(obj)) - return fz_throw("typecheck in arrayput"); + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); if (i < 0) - return fz_throw("rangecheck in arrayput: %d < 0", i); + return fz_throw("assert: index %d < 0", i); if (i >= obj->u.a.len) - return fz_throw("rangecheck in arrayput: %d > %d", i, obj->u.a.len); + return fz_throw("assert: index %d > length %d", i, obj->u.a.len); if (obj->u.a.items[i]) fz_dropobj(obj->u.a.items[i]); obj->u.a.items[i] = fz_keepobj(item); - return nil; + return fz_okay; } static fz_error * @@ -139,14 +181,15 @@ growarray(fz_obj *obj) newcap = obj->u.a.cap * 2; newitems = fz_realloc(obj->u.a.items, sizeof (fz_obj*) * newcap); - if (!newitems) return fz_outofmem; + if (!newitems) + return fz_throw("outofmem: resize item buffer"); obj->u.a.items = newitems; for (i = obj->u.a.cap ; i < newcap; i++) obj->u.a.items[i] = nil; obj->u.a.cap = newcap; - return nil; + return fz_okay; } fz_error * @@ -155,17 +198,19 @@ fz_arraypush(fz_obj *obj, fz_obj *item) fz_error *error; if (!fz_isarray(obj)) - return fz_throw("typecheck in arraypush"); + return fz_throw("assert: not an array (%s)", fz_objkindstr(obj)); - if (obj->u.a.len + 1 > obj->u.a.cap) { + if (obj->u.a.len + 1 > obj->u.a.cap) + { error = growarray(obj); - if (error) return error; + if (error) + return fz_rethrow(error, "cannot grow item buffer"); } obj->u.a.items[obj->u.a.len] = fz_keepobj(item); obj->u.a.len++; - return nil; + return fz_okay; } void diff --git a/stream/obj_dict.c b/stream/obj_dict.c index 0981e8a3..a93ae1bd 100644 --- a/stream/obj_dict.c +++ b/stream/obj_dict.c @@ -30,7 +30,8 @@ fz_newdict(fz_obj **op, int initialcap) int i; obj = *op = fz_malloc(sizeof (fz_obj)); - if (!obj) return fz_outofmem; + if (!obj) + return fz_throw("outofmem: dict struct"); obj->refs = 1; obj->kind = FZ_DICT; @@ -40,9 +41,14 @@ fz_newdict(fz_obj **op, int initialcap) obj->u.d.cap = initialcap > 0 ? initialcap : 10; obj->u.d.items = fz_malloc(sizeof(fz_keyval) * obj->u.d.cap); - if (!obj->u.d.items) { fz_free(obj); return fz_outofmem; } + if (!obj->u.d.items) + { + fz_free(obj); + return fz_throw("outofmem: dict item buffer"); + } - for (i = 0; i < obj->u.d.cap; i++) { + for (i = 0; i < obj->u.d.cap; i++) + { obj->u.d.items[i].k = nil; obj->u.d.items[i].v = nil; } @@ -58,18 +64,24 @@ fz_copydict(fz_obj **op, fz_obj *obj) int i; if (!fz_isdict(obj)) - return fz_throw("typecheck in copydict"); + return fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); error = fz_newdict(&new, obj->u.d.cap); - if (error) return error; - *op = new; + if (error) + return fz_rethrow(error, "cannot create new dict"); - for (i = 0; i < fz_dictlen(obj); i++) { + for (i = 0; i < fz_dictlen(obj); i++) + { error = fz_dictput(new, fz_dictgetkey(obj, i), fz_dictgetval(obj, i)); - if (error) { fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(new); + return fz_rethrow(error, "cannot copy dict entry"); + } } - return nil; + *op = new; + return fz_okay; } fz_error * @@ -81,39 +93,65 @@ fz_deepcopydict(fz_obj **op, fz_obj *obj) int i; if (!fz_isdict(obj)) - return fz_throw("typecheck in deepcopydict"); + return fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); error = fz_newdict(&new, obj->u.d.cap); - if (error) return error; - *op = new; + if (error) + return fz_rethrow(error, "cannot create new dict"); for (i = 0; i < fz_dictlen(obj); i++) { val = fz_dictgetval(obj, i); - if (fz_isarray(val)) { + if (fz_isarray(val)) + { error = fz_deepcopyarray(&val, val); - if (error) { fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(new); + return fz_rethrow(error, "cannot deep copy item"); + } error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropobj(val); fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(val); + fz_dropobj(new); + return fz_rethrow(error, "cannot add copied dict entry"); + } fz_dropobj(val); } - else if (fz_isdict(val)) { + else if (fz_isdict(val)) + { error = fz_deepcopydict(&val, val); - if (error) { fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(new); + return fz_rethrow(error, "cannot deep copy item"); + } error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropobj(val); fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(val); + fz_dropobj(new); + return fz_rethrow(error, "cannot add copied dict entry"); + } fz_dropobj(val); } - else { + else + { error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropobj(new); return error; } + if (error) + { + fz_dropobj(new); + return fz_rethrow(error, "cannot copy dict entry"); + } } } - return nil; + *op = new; + return fz_okay; } static fz_error * @@ -126,16 +164,18 @@ growdict(fz_obj *obj) newcap = obj->u.d.cap * 2; newitems = fz_realloc(obj->u.d.items, sizeof(fz_keyval) * newcap); - if (!newitems) return fz_outofmem; + if (!newitems) + return fz_throw("outofmem: resize item buffer"); obj->u.d.items = newitems; - for (i = obj->u.d.cap; i < newcap; i++) { + for (i = obj->u.d.cap; i < newcap; i++) + { obj->u.d.items[i].k = nil; obj->u.d.items[i].v = nil; } obj->u.d.cap = newcap; - return nil; + return fz_okay; } int @@ -243,28 +283,28 @@ fz_dictput(fz_obj *obj, fz_obj *key, fz_obj *val) int i; if (!fz_isdict(obj)) - return fz_throw("typecheck in dictput"); + return fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); if (fz_isname(key)) s = fz_toname(key); else if (fz_isstring(key)) s = fz_tostrbuf(key); else - return fz_throw("typecheck in dictput"); + return fz_throw("assert: key is not string or name (%s)", fz_objkindstr(obj)); i = dictfinds(obj, s); if (i >= 0) { fz_dropobj(obj->u.d.items[i].v); obj->u.d.items[i].v = fz_keepobj(val); - return nil; + return fz_okay; } if (obj->u.d.len + 1 > obj->u.d.cap) { error = growdict(obj); if (error) - return error; + return fz_rethrow(error, "cannot grow dict item buffer"); } /* borked! */ @@ -276,7 +316,7 @@ fz_dictput(fz_obj *obj, fz_obj *key, fz_obj *val) obj->u.d.items[obj->u.d.len].v = fz_keepobj(val); obj->u.d.len ++; - return nil; + return fz_okay; } fz_error * @@ -297,7 +337,7 @@ fz_dictdels(fz_obj *obj, char *key) int i; if (!fz_isdict(obj)) - return fz_throw("typecheck in dictdel"); + return fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); i = dictfinds(obj, key); if (i >= 0) @@ -309,7 +349,7 @@ fz_dictdels(fz_obj *obj, char *key) obj->u.d.len --; } - return nil; + return fz_okay; } fz_error * @@ -320,7 +360,7 @@ fz_dictdel(fz_obj *obj, fz_obj *key) else if (fz_isstring(key)) return fz_dictdels(obj, fz_tostrbuf(key)); else - return fz_throw("typecheck in dictdel"); + return fz_throw("assert: key is not string or name (%s)", fz_objkindstr(obj)); } void diff --git a/stream/obj_parse.c b/stream/obj_parse.c index 73b761cb..316e8ad4 100644 --- a/stream/obj_parse.c +++ b/stream/obj_parse.c @@ -62,6 +62,7 @@ static void parsekeyword(char **sp, char *b, char *eb) static fz_error *parsename(fz_obj **obj, char **sp) { + fz_error *error; char buf[64]; char *s = *sp; char *p = buf; @@ -72,11 +73,15 @@ static fz_error *parsename(fz_obj **obj, char **sp) *p++ = 0; *sp = s; - return fz_newname(obj, buf); + error = fz_newname(obj, buf); + if (error) + return fz_rethrow(error, "cannot create name"); + return fz_okay; } static fz_error *parsenumber(fz_obj **obj, char **sp) { + fz_error *error; char buf[32]; char *s = *sp; char *p = buf; @@ -92,8 +97,13 @@ static fz_error *parsenumber(fz_obj **obj, char **sp) *sp = s; if (strchr(buf, '.')) - return fz_newreal(obj, atof(buf)); - return fz_newint(obj, atoi(buf)); + error = fz_newreal(obj, atof(buf)); + else + error = fz_newint(obj, atoi(buf)); + + if (error) + return fz_rethrow(error, "cannot parse number"); + return fz_okay; } static fz_error *parsedict(fz_obj **obj, char **sp, struct vap *v) @@ -105,8 +115,8 @@ static fz_error *parsedict(fz_obj **obj, char **sp, struct vap *v) char *s = *sp; error = fz_newdict(&dict, 8); - if (error) return error; - *obj = dict; + if (error) + return fz_rethrow(error, "cannot create dict"); s += 2; /* skip "<<" */ @@ -115,39 +125,55 @@ static fz_error *parsedict(fz_obj **obj, char **sp, struct vap *v) skipwhite(&s); /* end-of-dict marker >> */ - if (*s == '>') { + if (*s == '>') + { s ++; - if (*s == '>') { + if (*s == '>') + { s ++; break; } - error = fz_throw("syntaxerror in parsedict"); + error = fz_throw("malformed >> marker"); goto cleanup; } /* non-name as key, bail */ - if (*s != '/') { - error = fz_throw("syntaxerror in parsedict"); + if (*s != '/') + { + error = fz_throw("key is not a name"); goto cleanup; } error = parsename(&key, &s); - if (error) goto cleanup; + if (error) + { + error = fz_rethrow(error, "cannot parse key"); + goto cleanup; + } skipwhite(&s); error = parseobj(&val, &s, v); - if (error) goto cleanup; + if (error) + { + error = fz_rethrow(error, "cannot parse value"); + goto cleanup; + } error = fz_dictput(dict, key, val); - if (error) goto cleanup; + if (error) + { + error = fz_rethrow(error, "cannot insert dict entry"); + goto cleanup; + } fz_dropobj(val); val = nil; fz_dropobj(key); key = nil; } + *obj = dict; *sp = s; - return nil; + return fz_okay; cleanup: if (val) fz_dropobj(val); @@ -166,8 +192,8 @@ static fz_error *parsearray(fz_obj **obj, char **sp, struct vap *v) char *s = *sp; error = fz_newarray(&a, 8); - if (error) return error; - *obj = a; + if (error) + return fz_rethrow(error, "cannot create array"); s ++; /* skip '[' */ @@ -175,26 +201,38 @@ static fz_error *parsearray(fz_obj **obj, char **sp, struct vap *v) { skipwhite(&s); - if (*s == ']') { + if (*s == ']') + { s ++; break; } error = parseobj(&o, &s, v); - if (error) { *obj = nil; fz_dropobj(a); return error; } + if (error) + { + fz_dropobj(a); + return fz_rethrow(error, "cannot parse item"); + } error = fz_arraypush(a, o); - if (error) { fz_dropobj(o); *obj = nil; fz_dropobj(a); return error; } + if (error) + { + fz_dropobj(o); + fz_dropobj(a); + return fz_rethrow(error, "cannot add item to array"); + } fz_dropobj(o); } + *obj = a; *sp = s; - return nil; + return fz_okay; } static fz_error *parsestring(fz_obj **obj, char **sp) { + fz_error *error; char buf[512]; char *s = *sp; char *p = buf; @@ -236,12 +274,12 @@ static fz_error *parsestring(fz_obj **obj, char **sp) } else switch (*s) { - case 'n': *p++ = '\n'; s++; break; - case 'r': *p++ = '\r'; s++; break; - case 't': *p++ = '\t'; s++; break; - case 'b': *p++ = '\b'; s++; break; - case 'f': *p++ = '\f'; s++; break; - default: *p++ = *s++; break; + case 'n': *p++ = '\n'; s++; break; + case 'r': *p++ = '\r'; s++; break; + case 't': *p++ = '\t'; s++; break; + case 'b': *p++ = '\b'; s++; break; + case 'f': *p++ = '\f'; s++; break; + default: *p++ = *s++; break; } } else @@ -252,11 +290,16 @@ static fz_error *parsestring(fz_obj **obj, char **sp) } *sp = s; - return fz_newstring(obj, buf, p - buf - 1); + + error = fz_newstring(obj, buf, p - buf - 1); + if (error) + return fz_rethrow(error, "cannot create string"); + return fz_okay; } static fz_error *parsehexstring(fz_obj **obj, char **sp) { + fz_error *error; char buf[512]; char *s = *sp; char *p = buf; @@ -287,7 +330,10 @@ static fz_error *parsehexstring(fz_obj **obj, char **sp) } *sp = s; - return fz_newstring(obj, buf, p - buf); + error = fz_newstring(obj, buf, p - buf); + if (error) + return fz_rethrow(error, "cannot create string"); + return fz_okay; } static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v) @@ -299,7 +345,7 @@ static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v) char *s = *sp; if (*s == '\0') - return fz_throw("syntaxerror in parseobj: end-of-string"); + return fz_throw("end of data"); skipwhite(&s); @@ -308,6 +354,7 @@ static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v) if (v != nil && *s == '%') { s ++; + switch (*s) { case 'p': error = fz_newpointer(obj, va_arg(v->ap, void*)); break; @@ -317,61 +364,102 @@ static fz_error *parseobj(fz_obj **obj, char **sp, struct vap *v) case 'f': error = fz_newreal(obj, (float)va_arg(v->ap, double)); break; case 'n': error = fz_newname(obj, va_arg(v->ap, char*)); break; case 'r': - oid = va_arg(v->ap, int); - gid = va_arg(v->ap, int); - error = fz_newindirect(obj, oid, gid); - break; + oid = va_arg(v->ap, int); + gid = va_arg(v->ap, int); + error = fz_newindirect(obj, oid, gid); + break; case 's': - tmp = va_arg(v->ap, char*); - error = fz_newstring(obj, tmp, strlen(tmp)); - break; + tmp = va_arg(v->ap, char*); + error = fz_newstring(obj, tmp, strlen(tmp)); + break; case '#': - tmp = va_arg(v->ap, char*); - len = va_arg(v->ap, int); - error = fz_newstring(obj, tmp, len); - break; + tmp = va_arg(v->ap, char*); + len = va_arg(v->ap, int); + error = fz_newstring(obj, tmp, len); + break; default: - error = fz_throw("unknown format specifier in packobj: '%c'", *s); - break; + error = fz_throw("unknown format specifier in packobj: '%c'", *s); + break; } + + if (error) + error = fz_rethrow(error, "cannot create object for %% format"); + s ++; } else if (*s == '/') + { error = parsename(obj, &s); + if (error) + error = fz_rethrow(error, "cannot parse name"); + } else if (*s == '(') + { error = parsestring(obj, &s); + if (error) + error = fz_rethrow(error, "cannot parse string"); + } - else if (*s == '<') { + else if (*s == '<') + { if (s[1] == '<') + { error = parsedict(obj, &s, v); + if (error) + error = fz_rethrow(error, "cannot parse dict"); + } else + { error = parsehexstring(obj, &s); + if (error) + error = fz_rethrow(error, "cannot parse hex string"); + } } else if (*s == '[') + { error = parsearray(obj, &s, v); + if (error) + error = fz_rethrow(error, "cannot parse array"); + } else if (*s == '-' || *s == '.' || (*s >= '0' && *s <= '9')) + { error = parsenumber(obj, &s); + if (error) + error = fz_rethrow(error, "cannot parse number"); + } else if (isregular(*s)) { parsekeyword(&s, buf, buf + sizeof buf); if (strcmp("true", buf) == 0) + { error = fz_newbool(obj, 1); + if (error) + error = fz_rethrow(error, "cannot create bool (true)"); + } else if (strcmp("false", buf) == 0) + { error = fz_newbool(obj, 0); + if (error) + error = fz_rethrow(error, "cannot create bool (false)"); + } else if (strcmp("null", buf) == 0) + { error = fz_newnull(obj); + if (error) + error = fz_rethrow(error, "cannot create null object"); + } else - error = fz_throw("syntaxerror in parseobj: undefined keyword %s", buf); + error = fz_throw("undefined keyword %s", buf); } else - error = fz_throw("syntaxerror in parseobj"); + error = fz_throw("syntax error: unknown byte 0x%d", *s); *sp = s; return error; @@ -388,6 +476,8 @@ fz_packobj(fz_obj **op, char *fmt, ...) va_copy(v.ap, ap); error = parseobj(op, &fmt, &v); + if (error) + error = fz_rethrow(error, "cannot parse object"); va_end(ap); diff --git a/stream/obj_simple.c b/stream/obj_simple.c index 77a7bca8..d8eb77b7 100644 --- a/stream/obj_simple.c +++ b/stream/obj_simple.c @@ -4,18 +4,18 @@ extern void fz_droparray(fz_obj *array); extern void fz_dropdict(fz_obj *dict); -#define NEWOBJ(KIND,SIZE) \ - fz_obj *o; \ - o = *op = fz_malloc(SIZE); \ - if (!o) return fz_outofmem; \ - o->refs = 1; \ - o->kind = KIND; \ +#define NEWOBJ(KIND,SIZE) \ + fz_obj *o; \ + o = *op = fz_malloc(SIZE); \ + if (!o) return fz_throw("outofmem: dynamic object"); \ + o->refs = 1; \ + o->kind = KIND; fz_error * fz_newnull(fz_obj **op) { NEWOBJ(FZ_NULL, sizeof (fz_obj)); - return nil; + return fz_okay; } fz_error * @@ -23,7 +23,7 @@ fz_newbool(fz_obj **op, int b) { NEWOBJ(FZ_BOOL, sizeof (fz_obj)); o->u.b = b; - return nil; + return fz_okay; } fz_error * @@ -31,7 +31,7 @@ fz_newint(fz_obj **op, int i) { NEWOBJ(FZ_INT, sizeof (fz_obj)); o->u.i = i; - return nil; + return fz_okay; } fz_error * @@ -39,7 +39,7 @@ fz_newreal(fz_obj **op, float f) { NEWOBJ(FZ_REAL, sizeof (fz_obj)); o->u.f = f; - return nil; + return fz_okay; } fz_error * @@ -49,7 +49,7 @@ fz_newstring(fz_obj **op, char *str, int len) o->u.s.len = len; memcpy(o->u.s.buf, str, len); o->u.s.buf[len] = '\0'; - return nil; + return fz_okay; } fz_error * @@ -57,7 +57,7 @@ fz_newname(fz_obj **op, char *str) { NEWOBJ(FZ_NAME, offsetof(fz_obj, u.n) + strlen(str) + 1); strcpy(o->u.n, str); - return nil; + return fz_okay; } fz_error * @@ -66,7 +66,7 @@ fz_newindirect(fz_obj **op, int objid, int genid) NEWOBJ(FZ_INDIRECT, sizeof (fz_obj)); o->u.r.oid = objid; o->u.r.gid = genid; - return nil; + return fz_okay; } fz_error * @@ -74,7 +74,7 @@ fz_newpointer(fz_obj **op, void *p) { NEWOBJ(FZ_POINTER, sizeof (fz_obj)); o->u.p = p; - return nil; + return fz_okay; } fz_obj * @@ -233,7 +233,7 @@ fz_topointer(fz_obj *obj) { if (fz_ispointer(obj)) return obj->u.p; - return nil; + return fz_okay; } fz_error * @@ -242,7 +242,7 @@ fz_newnamefromstring(fz_obj **op, fz_obj *str) NEWOBJ(FZ_NAME, offsetof(fz_obj, u.n) + fz_tostrlen(str) + 1); memcpy(o->u.n, fz_tostrbuf(str), fz_tostrlen(str)); o->u.n[fz_tostrlen(str)] = '\0'; - return nil; + return fz_okay; } int @@ -261,10 +261,12 @@ fz_objcmp(fz_obj *a, fz_obj *b) case FZ_BOOL: return a->u.b - b->u.b; case FZ_INT: return a->u.i - b->u.i; case FZ_REAL: return a->u.f - b->u.f; + case FZ_STRING: if (a->u.s.len != b->u.s.len) return a->u.s.len - b->u.s.len; return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len); + case FZ_NAME: return strcmp(a->u.n, b->u.n); @@ -299,3 +301,23 @@ fz_objcmp(fz_obj *a, fz_obj *b) return 1; } +char *fz_objkindstr(fz_obj *obj) +{ + if (obj == nil) + return "<nil>"; + switch (obj->kind) + { + case FZ_NULL: return "null"; + case FZ_BOOL: return "boolean"; + case FZ_INT: return "integer"; + case FZ_REAL: return "real"; + case FZ_STRING: return "string"; + case FZ_NAME: return "name"; + case FZ_ARRAY: return "array"; + case FZ_DICT: return "dictionary"; + case FZ_INDIRECT: return "reference"; + case FZ_POINTER: return "pointer"; + } + return "<unknown>"; +} + diff --git a/stream/stm_buffer.c b/stream/stm_buffer.c index 4fc5636c..8a1e0850 100644 --- a/stream/stm_buffer.c +++ b/stream/stm_buffer.c @@ -7,19 +7,24 @@ fz_newbuffer(fz_buffer **bp, int size) fz_buffer *b; b = *bp = fz_malloc(sizeof(fz_buffer)); - if (!b) return fz_outofmem; + if (!b) + return fz_throw("outofmem: buffer struct"); b->refs = 1; b->ownsdata = 1; b->bp = fz_malloc(size); - if (!b->bp) { fz_free(b); return fz_outofmem; } + if (!b->bp) + { + fz_free(b); + return fz_throw("outofmem: buffer memory"); + } b->rp = b->bp; b->wp = b->bp; b->ep = b->bp + size; b->eof = 0; - return nil; + return fz_okay; } fz_error * @@ -28,7 +33,8 @@ fz_newbufferwithmemory(fz_buffer **bp, unsigned char *data, int size) fz_buffer *b; b = *bp = fz_malloc(sizeof(fz_buffer)); - if (!b) return fz_outofmem; + if (!b) + return fz_throw("outofmem: buffer struct"); b->refs = 1; b->ownsdata = 0; @@ -39,7 +45,7 @@ fz_newbufferwithmemory(fz_buffer **bp, unsigned char *data, int size) b->ep = b->bp + size; b->eof = 0; - return nil; + return fz_okay; } fz_buffer * @@ -69,26 +75,31 @@ fz_growbuffer(fz_buffer *buf) int wp = buf->wp - buf->bp; int ep = buf->ep - buf->bp; - assert(buf->ownsdata); + if (!buf->ownsdata) + return fz_throw("assert: grow borrowed memory"); newbp = fz_realloc(buf->bp, ep * 2); - if (!newbp) return fz_outofmem; + if (!newbp) + return fz_throw("outofmem: resize buffer memory"); buf->bp = newbp; buf->rp = buf->bp + rp; buf->wp = buf->bp + wp; buf->ep = buf->bp + ep * 2; - return nil; + return fz_okay; } fz_error * fz_rewindbuffer(fz_buffer *buf) { - assert(buf->ownsdata); + if (!buf->ownsdata) + return fz_throw("assert: rewind borrowed memory"); + memmove(buf->bp, buf->rp, buf->wp - buf->rp); buf->wp = buf->bp + (buf->wp - buf->rp); buf->rp = buf->bp; - return nil; + + return fz_okay; } diff --git a/stream/stm_filter.c b/stream/stm_filter.c index c8091136..65b917d5 100644 --- a/stream/stm_filter.c +++ b/stream/stm_filter.c @@ -1,9 +1,9 @@ #include "fitz-base.h" #include "fitz-stream.h" -fz_error fz_kioneedin = { -1, "<ioneedin>", "<process>", "filter.c", 0 }; -fz_error fz_kioneedout = { -1, "<ioneedout>", "<process>", "filter.c", 0 }; -fz_error fz_kiodone = { -1, "<iodone>", "<process>", "filter.c", 0 }; +fz_error fz_kioneedin = { -1, "<ioneedin>", "<internal>", "<internal>", 0, 0 }; +fz_error fz_kioneedout = { -1, "<ioneedout>", "<internal>", "<internal>", 0, 0 }; +fz_error fz_kiodone = { -1, "<iodone>", "<internal>", "<internal>", 0, 0 }; fz_error * fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out) @@ -27,7 +27,11 @@ fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out) f->count += out->wp - oldwp; if (reason != fz_ioneedin && reason != fz_ioneedout) + { + if (reason != fz_iodone) + reason = fz_rethrow(reason, "cannot process filter"); out->eof = 1; + } return reason; } diff --git a/stream/stm_misc.c b/stream/stm_misc.c index bc739055..22d993d1 100644 --- a/stream/stm_misc.c +++ b/stream/stm_misc.c @@ -5,14 +5,16 @@ #include "fitz-base.h" #include "fitz-stream.h" -int fz_tell(fz_stream *stm) +int +fz_tell(fz_stream *stm) { if (stm->mode == FZ_SREAD) return fz_rtell(stm); return fz_wtell(stm); } -int fz_seek(fz_stream *stm, int offset, int whence) +fz_error * +fz_seek(fz_stream *stm, int offset, int whence) { if (stm->mode == FZ_SREAD) return fz_rseek(stm, offset, whence); @@ -23,8 +25,11 @@ int fz_seek(fz_stream *stm, int offset, int whence) * Read a line terminated by LF or CR or CRLF. */ -int fz_readline(fz_stream *stm, char *mem, int n) +fz_error * +fz_readline(fz_stream *stm, char *mem, int n) { + fz_error *error; + char *s = mem; int c = EOF; while (n > 1) @@ -45,7 +50,11 @@ int fz_readline(fz_stream *stm, char *mem, int n) } if (n) *s = '\0'; - return s - mem; + + error = fz_readerror(stm); + if (error) + return fz_rethrow(error, "cannot read line"); + return fz_okay; } /* @@ -55,8 +64,10 @@ int fz_readline(fz_stream *stm, char *mem, int n) enum { CHUNKSIZE = 1024 * 4 }; -int fz_readall(fz_buffer **bufp, fz_stream *stm) +fz_error * +fz_readall(fz_buffer **bufp, fz_stream *stm) { + fz_error *error; fz_buffer *real; unsigned char *newbuf; unsigned char *buf; @@ -64,8 +75,6 @@ int fz_readall(fz_buffer **bufp, fz_stream *stm) int pos; int n; - *bufp = nil; - len = 0; pos = 0; buf = nil; @@ -79,17 +88,16 @@ int fz_readall(fz_buffer **bufp, fz_stream *stm) if (!newbuf) { fz_free(buf); - return -1; + return fz_throw("outofmem: scratch buffer"); } buf = newbuf; } - n = fz_read(stm, buf + pos, len - pos); - - if (n < 0) + error = fz_read(&n, stm, buf + pos, len - pos); + if (error) { fz_free(buf); - return -1; + return fz_rethrow(error, "cannot read data"); } pos += n; @@ -102,16 +110,16 @@ int fz_readall(fz_buffer **bufp, fz_stream *stm) if (!newbuf) { fz_free(buf); - return -1; + return fz_throw("outofmem: scratch buffer"); } } else newbuf = buf; - real = *bufp = fz_malloc(sizeof(fz_buffer)); + real = fz_malloc(sizeof(fz_buffer)); if (!real) { fz_free(newbuf); - return -1; + return fz_throw("outofmem: buffer struct"); } real->refs = 1; @@ -122,7 +130,8 @@ int fz_readall(fz_buffer **bufp, fz_stream *stm) real->ep = buf + pos; real->eof = 1; - return real->wp - real->rp; + *bufp = real; + return fz_okay; } } } diff --git a/stream/stm_open.c b/stream/stm_open.c index 43d2a60b..c10d1509 100644 --- a/stream/stm_open.c +++ b/stream/stm_open.c @@ -28,19 +28,6 @@ newstm(int kind, int mode) return stm; } -fz_error * -fz_ioerror(fz_stream *stm) -{ - fz_error *error; - if (stm->error) - { - error = stm->error; - stm->error = nil; - return error; - } - return fz_throw("ioerror: no error"); -} - fz_stream * fz_keepstream(fz_stream *stm) { @@ -56,7 +43,7 @@ fz_dropstream(fz_stream *stm) { if (stm->error) { - fz_warn("unhandled %s", stm->error->msg); + fz_warn("dropping unhandled ioerror"); fz_droperror(stm->error); } @@ -92,13 +79,13 @@ openfile(fz_stream **stmp, char *path, int mode, int realmode) stm = newstm(FZ_SFILE, mode); if (!stm) - return fz_outofmem; + return fz_throw("outofmem: stream struct"); error = fz_newbuffer(&stm->buffer, FZ_BUFSIZE); if (error) { fz_free(stm); - return error; + return fz_rethrow(error, "cannot create buffer"); } stm->file = open(path, realmode, 0666); @@ -106,11 +93,11 @@ openfile(fz_stream **stmp, char *path, int mode, int realmode) { fz_dropbuffer(stm->buffer); fz_free(stm); - return fz_throw("ioerror: open '%s' failed: %s", path, strerror(errno)); + return fz_throw("syserr: open '%s': %s", path, strerror(errno)); } *stmp = stm; - return nil; + return fz_okay; } static fz_error * @@ -121,20 +108,20 @@ openfilter(fz_stream **stmp, fz_filter *flt, fz_stream *src, int mode) stm = newstm(FZ_SFILTER, mode); if (!stm) - return fz_outofmem; + return fz_throw("outofmem: stream struct"); error = fz_newbuffer(&stm->buffer, FZ_BUFSIZE); if (error) { fz_free(stm); - return error; + return fz_rethrow(error, "cannot create buffer"); } stm->chain = fz_keepstream(src); stm->filter = fz_keepfilter(flt); *stmp = stm; - return nil; + return fz_okay; } static fz_error * @@ -144,7 +131,7 @@ openbuffer(fz_stream **stmp, fz_buffer *buf, int mode) stm = newstm(FZ_SBUFFER, mode); if (!stm) - return fz_outofmem; + return fz_throw("outofmem: stream struct"); stm->buffer = fz_keepbuffer(buf); @@ -152,18 +139,26 @@ openbuffer(fz_stream **stmp, fz_buffer *buf, int mode) stm->buffer->eof = 1; *stmp = stm; - return nil; + return fz_okay; } fz_error * fz_openrfile(fz_stream **stmp, char *path) { - return openfile(stmp, path, FZ_SREAD, O_BINARY | O_RDONLY); + fz_error *error; + error = openfile(stmp, path, FZ_SREAD, O_BINARY | O_RDONLY); + if (error) + return fz_rethrow(error, "cannot open file for reading: '%s'", path); + return fz_okay; } fz_error * fz_openwfile(fz_stream **stmp, char *path) { - return openfile(stmp, path, FZ_SWRITE, + fz_error *error; + error = openfile(stmp, path, FZ_SWRITE, O_BINARY | O_WRONLY | O_CREAT | O_TRUNC); + if (error) + return fz_rethrow(error, "cannot open file for writing: '%s'", path); + return fz_okay; } fz_error * fz_openafile(fz_stream **stmp, char *path) @@ -173,51 +168,72 @@ fz_error * fz_openafile(fz_stream **stmp, char *path) error = openfile(stmp, path, FZ_SWRITE, O_BINARY | O_WRONLY); if (error) - return error; + return fz_rethrow(error, "cannot open file for writing: '%s'", path); t = lseek((*stmp)->file, 0, 2); if (t < 0) { (*stmp)->dead = 1; - return fz_throw("ioerror: lseek: %s", strerror(errno)); + return fz_throw("syserr: lseek '%s': %s", path, strerror(errno)); } - return nil; + return fz_okay; } fz_error * fz_openrfilter(fz_stream **stmp, fz_filter *flt, fz_stream *src) { - return openfilter(stmp, flt, src, FZ_SREAD); + fz_error *error; + error = openfilter(stmp, flt, src, FZ_SREAD); + if (error) + return fz_rethrow(error, "cannot create reading filter stream"); + return fz_okay; } fz_error * fz_openwfilter(fz_stream **stmp, fz_filter *flt, fz_stream *src) { - return openfilter(stmp, flt, src, FZ_SWRITE); + fz_error *error; + error = openfilter(stmp, flt, src, FZ_SWRITE); + if (error) + return fz_rethrow(error, "cannot create writing filter stream"); + return fz_okay; } fz_error * fz_openrbuffer(fz_stream **stmp, fz_buffer *buf) { - return openbuffer(stmp, buf, FZ_SREAD); + fz_error *error; + error = openbuffer(stmp, buf, FZ_SREAD); + if (error) + return fz_rethrow(error, "cannot create reading buffer stream"); + return fz_okay; } fz_error * fz_openwbuffer(fz_stream **stmp, fz_buffer *buf) { - return openbuffer(stmp, buf, FZ_SWRITE); + fz_error *error; + error = openbuffer(stmp, buf, FZ_SWRITE); + if (error) + return fz_rethrow(error, "cannot create writing buffer stream"); + return fz_okay; } -fz_error * fz_openrmemory(fz_stream **stmp, unsigned char *mem, int len) +fz_error * fz_openrmemory(fz_stream **stmp, char *mem, int len) { fz_error *error; fz_buffer *buf; error = fz_newbufferwithmemory(&buf, mem, len); if (error) - return error; + return fz_rethrow(error, "cannot create memory buffer"); error = fz_openrbuffer(stmp, buf); + if (error) + { + fz_dropbuffer(buf); + return fz_rethrow(error, "cannot open memory buffer stream"); + } fz_dropbuffer(buf); - return error; + return fz_okay; } diff --git a/stream/stm_read.c b/stream/stm_read.c index 0ab7e076..43bdb192 100644 --- a/stream/stm_read.c +++ b/stream/stm_read.c @@ -5,8 +5,8 @@ #include "fitz-base.h" #include "fitz-stream.h" -int -fz_makedata(fz_stream *stm) +fz_error * +fz_readimp(fz_stream *stm) { fz_buffer *buf = stm->buffer; fz_error *error; @@ -15,23 +15,29 @@ fz_makedata(fz_stream *stm) int n; if (stm->dead) - return -1; + return fz_throw("assert: read from dead stream"); if (stm->mode != FZ_SREAD) - return -1; + return fz_throw("assert: read from writing stream"); if (buf->eof) - return 0; + return fz_okay; error = fz_rewindbuffer(buf); if (error) - goto cleanup; + { + stm->dead = 1; + return fz_rethrow(error, "cannot rewind output buffer"); + } if (buf->ep - buf->wp == 0) { error = fz_growbuffer(buf); if (error) - goto cleanup; + { + stm->dead = 1; + return fz_rethrow(error, "cannot grow output buffer"); + } } switch (stm->kind) @@ -41,14 +47,15 @@ fz_makedata(fz_stream *stm) n = read(stm->file, buf->wp, buf->ep - buf->wp); if (n == -1) { - stm->error = fz_throw("ioerror: read: %s", strerror(errno)); stm->dead = 1; - return -1; + return fz_throw("syserr: read: %s", strerror(errno)); } + if (n == 0) buf->eof = 1; buf->wp += n; - return n; + + return fz_okay; case FZ_SFILTER: produced = 0; @@ -62,10 +69,11 @@ fz_makedata(fz_stream *stm) if (reason == fz_ioneedin) { - if (fz_makedata(stm->chain) < 0) + error = fz_readimp(stm->chain); + if (error) { stm->dead = 1; - return -1; + return fz_rethrow(error, "cannot read from input stream"); } } @@ -78,50 +86,52 @@ fz_makedata(fz_stream *stm) { error = fz_rewindbuffer(buf); if (error) - goto cleanup; + { + stm->dead = 1; + return fz_rethrow(error, "cannot rewind buffer"); + } } else { error = fz_growbuffer(buf); if (error) - goto cleanup; + { + stm->dead = 1; + return fz_rethrow(error, "cannot grow buffer"); + } } } else if (reason == fz_iodone) { - return 0; + return fz_okay; } else { - error = reason; - goto cleanup; + stm->dead = 1; + return fz_rethrow(reason, "cannot process filter"); } } case FZ_SBUFFER: - return 0; - } + return fz_okay; - return -1; - -cleanup: - stm->error = error; - stm->dead = 1; - return -1; + default: + return fz_throw("assert: unknown stream type"); + } } -int fz_rtell(fz_stream *stm) +int +fz_rtell(fz_stream *stm) { fz_buffer *buf = stm->buffer; int t; if (stm->dead) - return -1; - + return EOF; if (stm->mode != FZ_SREAD) - return -1; + return EOF; switch (stm->kind) { @@ -129,8 +139,9 @@ int fz_rtell(fz_stream *stm) t = lseek(stm->file, 0, 1); if (t < 0) { + fz_warn("syserr: lseek: %s", strerror(errno)); stm->dead = 1; - return -1; + return EOF; } return t - (buf->wp - buf->rp); @@ -139,27 +150,30 @@ int fz_rtell(fz_stream *stm) case FZ_SBUFFER: return buf->rp - buf->bp; - } - return -1; + default: + return EOF; + } } -int fz_rseek(fz_stream *stm, int offset, int whence) +fz_error * +fz_rseek(fz_stream *stm, int offset, int whence) { + fz_error *error; fz_buffer *buf = stm->buffer; int t, c; if (stm->dead) - return -1; + return fz_throw("assert: seek in dead stream"); if (stm->mode != FZ_SREAD) - return -1; + return fz_throw("assert: read operation on writing stream"); if (whence == 1) { int cur = fz_rtell(stm); if (cur < 0) - return -1; + return fz_throw("cannot tell current position"); offset = cur + offset; whence = 0; } @@ -172,103 +186,128 @@ int fz_rseek(fz_stream *stm, int offset, int whence) t = lseek(stm->file, offset, whence); if (t < 0) { - stm->error = fz_throw("ioerror: lseek: %s", strerror(errno)); stm->dead = 1; - return -1; + return fz_throw("syserr: lseek: %s", strerror(errno)); } buf->rp = buf->bp; buf->wp = buf->bp; - return t; + return fz_okay; case FZ_SFILTER: if (whence == 0) { - if (offset < fz_tell(stm)) + if (offset < fz_rtell(stm)) { - stm->error = fz_throw("ioerror: cannot seek back in filter"); stm->dead = 1; - return -1; + return fz_throw("assert: seek backwards in filter"); } - while (fz_tell(stm) < offset) + while (fz_rtell(stm) < offset) { c = fz_readbyte(stm); if (c == EOF) + { + error = fz_readerror(stm); + if (error) + return fz_rethrow(error, "cannot seek forward in filter"); break; + } } - return fz_tell(stm); - } - else - { - stm->dead = 1; - return -1; + return fz_okay; } + stm->dead = 1; + return fz_throw("assert: relative seek in filter"); + case FZ_SBUFFER: if (whence == 0) buf->rp = CLAMP(buf->bp + offset, buf->bp, buf->ep); else buf->rp = CLAMP(buf->ep + offset, buf->bp, buf->ep); - return buf->rp - buf->bp; - } + return fz_okay; - return -1; + default: + return fz_throw("unknown stream type"); + } } -int fz_readbytex(fz_stream *stm) +fz_error * +fz_read(int *np, fz_stream *stm, unsigned char *mem, int n) { + fz_error *error; fz_buffer *buf = stm->buffer; - if (buf->rp == buf->wp) + int i = 0; + + while (i < n) { - if (buf->eof) return EOF; - if (fz_makedata(stm) < 0) return EOF; + while (buf->rp < buf->wp && i < n) + mem[i++] = *buf->rp++; + + if (buf->rp == buf->wp) + { + if (buf->eof) + { + *np = i; + return fz_okay; + } + + error = fz_readimp(stm); + if (error) + return fz_rethrow(error, "cannot produce data"); + } } - if (buf->rp < buf->wp) - return *buf->rp++; - return EOF; + + *np = i; + return fz_okay; } -int fz_peekbytex(fz_stream *stm) +fz_error * +fz_readerror(fz_stream *stm) +{ + fz_error *error; + if (stm->error) + { + error = stm->error; + stm->error = nil; + return fz_rethrow(error, "delayed read error"); + } + return fz_okay; +} + +int +fz_readbytex(fz_stream *stm) { fz_buffer *buf = stm->buffer; + if (buf->rp == buf->wp) { - if (buf->eof) return EOF; - if (fz_makedata(stm) < 0) return EOF; + if (!buf->eof && !stm->error) + { + fz_error *error = fz_readimp(stm); + if (error) + stm->error = fz_rethrow(error, "cannot read data"); + } } - if (buf->rp < buf->wp) - return *buf->rp; - return EOF; + + return buf->rp < buf->wp ? *buf->rp++ : EOF ; } -int fz_read(fz_stream *stm, unsigned char * restrict mem, int n) +int +fz_peekbytex(fz_stream *stm) { fz_buffer *buf = stm->buffer; - int i = 0; - while (i < n) + if (buf->rp == buf->wp) { -#if 0 - while (buf->rp < buf->wp && i < n) - mem[i++] = *buf->rp++; -#else - int l = buf->wp - buf->rp; - int ln = n; - unsigned char * restrict src = buf->rp; - ln = MIN(n - i, l) + i; - while (i < ln) { - mem[i++] = *src++; - } - buf->rp = src; -#endif - if (buf->rp == buf->wp) + if (!buf->eof && !stm->error) { - if (buf->eof) return i; - if (fz_makedata(stm) < 0) return -1; + fz_error *error = fz_readimp(stm); + if (error) + stm->error = fz_rethrow(error, "cannot read data"); } } - return i; + return buf->rp < buf->wp ? *buf->rp : EOF ; } diff --git a/stream/stm_write.c b/stream/stm_write.c index f619da9c..23b268d9 100644 --- a/stream/stm_write.c +++ b/stream/stm_write.c @@ -5,16 +5,17 @@ #include "fitz-base.h" #include "fitz-stream.h" -int fz_wtell(fz_stream *stm) +int +fz_wtell(fz_stream *stm) { fz_buffer *buf = stm->buffer; int t; if (stm->dead) - return -1; + return EOF; if (stm->mode != FZ_SWRITE) - return -1; + return EOF; switch (stm->kind) { @@ -22,9 +23,9 @@ int fz_wtell(fz_stream *stm) t = lseek(stm->file, 0, 1); if (t < 0) { - stm->error = fz_throw("ioerror: lseek: %s", strerror(errno)); + fz_warn("syserr: lseek: %s", strerror(errno)); stm->dead = 1; - return -1; + return EOF; } return t + (buf->wp - buf->rp); @@ -33,46 +34,47 @@ int fz_wtell(fz_stream *stm) case FZ_SBUFFER: return buf->wp - buf->bp; - } - return -1; + default: + return EOF; + } } -int fz_wseek(fz_stream *stm, int offset, int whence) +fz_error * +fz_wseek(fz_stream *stm, int offset, int whence) { fz_buffer *buf = stm->buffer; int t; if (stm->dead) - return -1; + return fz_throw("assert: seek in dead stream"); if (stm->mode != FZ_SWRITE) - return -1; + return fz_throw("assert: write operation on reading stream"); if (stm->kind != FZ_SFILE) - return -1; + return fz_throw("assert: write seek on non-file stream"); t = lseek(stm->file, offset, whence); if (t < 0) { - stm->error = fz_throw("ioerror: lseek: %s", strerror(errno)); stm->dead = 1; - return -1; + return fz_throw("syserr: lseek: %s", strerror(errno)); } buf->rp = buf->bp; buf->wp = buf->bp; buf->eof = 0; - return t; + return fz_okay; } -static int flushfilter(fz_stream *stm) +static fz_error * +fz_flushfilterimp(fz_stream *stm) { fz_buffer *buf = stm->buffer; fz_error *error; fz_error *reason; - int t; loop: @@ -81,20 +83,30 @@ loop: if (reason == fz_ioneedin) { if (buf->rp > buf->ep) - fz_rewindbuffer(buf); + { + error = fz_rewindbuffer(buf); + if (error) + { + stm->dead = 1; + return fz_rethrow(error, "cannot rewind buffer"); + } + } else { error = fz_growbuffer(buf); if (error) - goto cleanup; + { + stm->dead = 1; + return fz_rethrow(error, "cannot grow buffer"); + } } } else if (reason == fz_ioneedout) { - t = fz_flush(stm->chain); - if (t < 0) - return -1; + error = fz_flush(stm->chain); + if (error) + return fz_rethrow(error, "cannot flush chain buffer"); } else if (reason == fz_iodone) @@ -104,20 +116,15 @@ loop: else { - error = reason; - goto cleanup; + stm->dead = 1; + return fz_rethrow(reason, "cannot process filter"); } /* if we are at eof, repeat until other filter sets otherside to eof */ if (buf->eof && !stm->chain->buffer->eof) goto loop; - return 0; - -cleanup: - stm->error = error; - stm->dead = 1; - return -1; + return fz_okay; } /* @@ -126,20 +133,21 @@ cleanup: * Called by fz_write and fz_dropstream. * If buffer is eof, then all data must be flushed. */ -int fz_flush(fz_stream *stm) +fz_error * +fz_flush(fz_stream *stm) { fz_buffer *buf = stm->buffer; fz_error *error; int t; - if (stm->dead == 2) - return 0; + if (stm->dead == 2) /* eod flag */ + return fz_okay; if (stm->dead) - return -1; + return fz_throw("assert: flush on dead stream"); if (stm->mode != FZ_SWRITE) - return -1; + return fz_throw("assert: write operation on reading stream"); switch (stm->kind) { @@ -149,21 +157,30 @@ int fz_flush(fz_stream *stm) t = write(stm->file, buf->rp, buf->wp - buf->rp); if (t < 0) { - stm->error = fz_throw("ioerror: write: %s", strerror(errno)); stm->dead = 1; - return -1; + return fz_throw("syserr: write: %s", strerror(errno)); } buf->rp += t; } if (buf->rp > buf->bp) - fz_rewindbuffer(buf); + { + error = fz_rewindbuffer(buf); + if (error) + { + stm->dead = 1; + return fz_rethrow(error, "cannot rewind buffer"); + } + } - return 0; + return fz_okay; case FZ_SFILTER: - return flushfilter(stm); + error = fz_flushfilterimp(stm); + if (error) + return fz_rethrow(error, "cannot flush through filter"); + return fz_okay; case FZ_SBUFFER: if (!buf->eof && buf->wp == buf->ep) @@ -171,36 +188,35 @@ int fz_flush(fz_stream *stm) error = fz_growbuffer(buf); if (error) { - stm->error = error; stm->dead = 1; - return -1; + return fz_rethrow(error, "cannot grow buffer"); } } - return 0; - } + return fz_okay; - return -1; + default: + return fz_throw("unknown stream type"); + } } /* * Write data to stream. * Buffer until internal buffer is full. * When full, call fz_flush to make more space available. + * Return error if all the data could not be written. */ -int fz_write(fz_stream *stm, unsigned char *mem, int n) +fz_error * +fz_write(fz_stream *stm, unsigned char *mem, int n) { fz_buffer *buf = stm->buffer; + fz_error *error; int i = 0; - int t; - - if (stm->dead == 2) - return 0; if (stm->dead) - return -1; + return fz_throw("assert: write on dead stream"); if (stm->mode != FZ_SWRITE) - return -1; + return fz_throw("assert: write on reading stream"); while (i < n) { @@ -209,24 +225,27 @@ int fz_write(fz_stream *stm, unsigned char *mem, int n) if (buf->wp == buf->ep && i < n) { - t = fz_flush(stm); - if (t < 0) - return -1; + error = fz_flush(stm); + if (error) + return fz_rethrow(error, "cannot flush buffer"); if (stm->dead) - return i; + return fz_throw("assert: write on dead stream"); } } - return n; + return fz_okay; } -int fz_printstr(fz_stream *stm, char *s) +fz_error * +fz_printstr(fz_stream *stm, char *s) { - return fz_write(stm, (unsigned char *) s, strlen(s)); + return fz_write(stm, s, strlen(s)); } -int fz_printobj(fz_stream *file, fz_obj *obj, int tight) +fz_error * +fz_printobj(fz_stream *file, fz_obj *obj, int tight) { + fz_error *error; char buf[1024]; char *ptr; int n; @@ -235,22 +254,29 @@ int fz_printobj(fz_stream *file, fz_obj *obj, int tight) if (n < sizeof buf) { fz_sprintobj(buf, sizeof buf, obj, tight); - return fz_write(file, (unsigned char *) buf, n); + error = fz_write(file, buf, n); + if (error) + return fz_rethrow(error, "cannot write buffer"); + return fz_okay; } else { ptr = fz_malloc(n); if (!ptr) - return -1; + return fz_throw("outofmem: scratch buffer"); fz_sprintobj(ptr, n, obj, tight); - n = fz_write(file, (unsigned char *) ptr, n); + error = fz_write(file, ptr, n); + if (error) + error = fz_rethrow(error, "cannot write buffer"); fz_free(ptr); - return n; + return error; } } -int fz_print(fz_stream *stm, char *fmt, ...) +fz_error * +fz_print(fz_stream *stm, char *fmt, ...) { + fz_error *error; va_list ap; char buf[1024]; char *p; @@ -261,20 +287,27 @@ int fz_print(fz_stream *stm, char *fmt, ...) va_end(ap); if (n < sizeof buf) - return fz_write(stm, (unsigned char *) buf, n); + { + error = fz_write(stm, buf, n); + if (error) + return fz_rethrow(error, "cannot write buffer"); + return fz_okay; + } p = fz_malloc(n); if (!p) - return -1; + return fz_throw("outofmem: scratch buffer"); va_start(ap, fmt); vsnprintf(p, n, fmt, ap); va_end(ap); - n = fz_write(stm, (unsigned char *) p, n); + error = fz_write(stm, p, n); + if (error) + error = fz_rethrow(error, "cannot write buffer"); fz_free(p); - return n; + return error; } diff --git a/world/node_optimize.c b/world/node_optimize.c index 7ee92496..69ca59cc 100644 --- a/world/node_optimize.c +++ b/world/node_optimize.c @@ -303,6 +303,8 @@ static fz_error *clean1x1(fz_node *node) fz_error * fz_optimizetree(fz_tree *tree) { + if (getenv("DONTOPT")) + return nil; cleanwhite(tree->root); cleanovers(tree->root); cleanmasks(tree->root); diff --git a/world/node_path.c b/world/node_path.c index b64d0742..dfae1560 100644 --- a/world/node_path.c +++ b/world/node_path.c @@ -232,12 +232,15 @@ fz_boundpathnode(fz_pathnode *path, fz_matrix ctm) } void -fz_debugpathnode(fz_pathnode *path) +fz_printpathnode(fz_pathnode *path, int indent) { float x, y; int i = 0; + int n; while (i < path->len) { + for (n = 0; n < indent; n++) + putchar(' '); switch (path->els[i++].k) { case FZ_MOVETO: @@ -266,6 +269,9 @@ fz_debugpathnode(fz_pathnode *path) } } + for (n = 0; n < indent; n++) + putchar(' '); + switch (path->paint) { case FZ_STROKE: @@ -280,6 +286,45 @@ fz_debugpathnode(fz_pathnode *path) } } +void +fz_debugpathnode(fz_pathnode *path, int indent) +{ + float x, y; + int i = 0; + int n; + while (i < path->len) + { + for (n = 0; n < indent; n++) + putchar(' '); + switch (path->els[i++].k) + { + case FZ_MOVETO: + x = path->els[i++].v; + y = path->els[i++].v; + printf("<moveto x=\"%g\" y=\"%g\" />\n", x, y); + break; + case FZ_LINETO: + x = path->els[i++].v; + y = path->els[i++].v; + printf("<lineto x=\"%g\" y=\"%g\" />\n", x, y); + break; + case FZ_CURVETO: + x = path->els[i++].v; + y = path->els[i++].v; + printf("<curveto x1=\"%g\" y1=\"%g\" ", x, y); + x = path->els[i++].v; + y = path->els[i++].v; + printf("x2=\"%g\" y2=\"%g\" ", x, y); + x = path->els[i++].v; + y = path->els[i++].v; + printf("x3=\"%g\" y3=\"%g\" />\n", x, y); + break; + case FZ_CLOSEPATH: + printf("<closepath />\n"); + } + } +} + fz_error * fz_newdash(fz_dash **dashp, float phase, int len, float *array) { diff --git a/world/node_toxml.c b/world/node_toxml.c index c6cf146e..ad2143c4 100644 --- a/world/node_toxml.c +++ b/world/node_toxml.c @@ -49,7 +49,7 @@ static void xmlblend(fz_blendnode *node, int level) { fz_node *child; indent(level); - printf("<blend mode=\"%d\" refs=\"%d\">\n", node->mode, node->cs->refs); + printf("<blend mode=\"%d\">\n", node->mode); for (child = node->super.first; child; child = child->next) xmlnode(child, level + 1); indent(level); @@ -60,9 +60,9 @@ static void xmltransform(fz_transformnode *node, int level) { indent(level); printf("<transform matrix=\"%g %g %g %g %g %g\">\n", - node->m.a, node->m.b, - node->m.c, node->m.d, - node->m.e, node->m.f); + node->m.a, node->m.b, + node->m.c, node->m.d, + node->m.e, node->m.f); xmlnode(node->super.first, level + 1); indent(level); printf("</transform>\n"); @@ -79,13 +79,13 @@ static void xmlsolid(fz_solidnode *node, int level) if (i < node->n - 1) putchar(' '); } - printf("\" refs=\"%d\" />\n", node->cs->refs); + printf("\" />\n"); } static void xmllink(fz_linknode *node, int level) { indent(level); - printf("<link name=\"%p\" refs=\"%d\" />\n", (void *) node->tree, node->tree->refs); + printf("<link name=\"%p\" />\n", node->tree); } static void xmlpath(fz_pathnode *node, int level) @@ -97,10 +97,10 @@ static void xmlpath(fz_pathnode *node, int level) if (node->paint == FZ_STROKE) { printf("<path fill=\"stroke\" cap=\"%d\" join=\"%d\" width=\"%g\" miter=\"%g\"", - node->linecap, - node->linejoin, - node->linewidth, - node->miterlimit); + node->linecap, + node->linejoin, + node->linewidth, + node->miterlimit); if (node->dash) { printf(" phase=\"%g\" array=\"", node->dash->phase); @@ -116,7 +116,7 @@ static void xmlpath(fz_pathnode *node, int level) node->paint == FZ_FILL ? "nonzero" : "evenodd"); } - fz_debugpathnode(node); + fz_debugpathnode(node, level + 2); indent(level); printf("</path>\n"); @@ -128,7 +128,7 @@ static void xmltext(fz_textnode *node, int level) indent(level); printf("<text font=\"%s\" matrix=\"%g %g %g %g\">\n", node->font->name, - node->trm.a, node->trm.b, node->trm.c, node->trm.d); + node->trm.a, node->trm.b, node->trm.c, node->trm.d); for (i = 0; i < node->len; i++) { @@ -149,14 +149,14 @@ static void xmlimage(fz_imagenode *node, int level) { fz_image *image = node->image; indent(level); - printf("<image w=\"%d\" h=\"%d\" n=\"%d\" a=\"%d\" refs=\"%d\" />\n", - image->w, image->h, image->n, image->a, image->refs); + printf("<image w=\"%d\" h=\"%d\" n=\"%d\" a=\"%d\" />\n", + image->w, image->h, image->n, image->a); } static void xmlshade(fz_shadenode *node, int level) { indent(level); - printf("<shade refs=\"%d\" />\n", node->shade->refs); + printf("<shade />\n"); } static void xmlnode(fz_node *node, int level) |