~ubuntu-branches/ubuntu/karmic/tiff/karmic-security

« back to all changes in this revision

Viewing changes to libtiff/tif_fax3.h

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-10-14 07:57:59 UTC
  • Revision ID: james.westby@ubuntu.com-20041014075759-a77e7zuaetya8cp0
Tags: upstream-3.6.1
ImportĀ upstreamĀ versionĀ 3.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: tif_fax3.h,v 1.4 2000/12/01 15:46:46 warmerda Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1990-1997 Sam Leffler
 
5
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
 
6
 *
 
7
 * Permission to use, copy, modify, distribute, and sell this software and 
 
8
 * its documentation for any purpose is hereby granted without fee, provided
 
9
 * that (i) the above copyright notices and this permission notice appear in
 
10
 * all copies of the software and related documentation, and (ii) the names of
 
11
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
 
12
 * publicity relating to the software without the specific, prior written
 
13
 * permission of Sam Leffler and Silicon Graphics.
 
14
 * 
 
15
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
 
16
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
 
17
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
 
18
 * 
 
19
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
 
20
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
 
21
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
22
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
 
23
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
 
24
 * OF THIS SOFTWARE.
 
25
 */
 
26
 
 
27
#ifndef _FAX3_
 
28
#define _FAX3_
 
29
/*
 
30
 * TIFF Library.
 
31
 *
 
32
 * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
 
33
 *
 
34
 * Decoder support is derived, with permission, from the code
 
35
 * in Frank Cringle's viewfax program;
 
36
 *      Copyright (C) 1990, 1995  Frank D. Cringle.
 
37
 */
 
38
#include "tiff.h"
 
39
 
 
40
/*
 
41
 * To override the default routine used to image decoded
 
42
 * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
 
43
 * The routine must have the type signature given below;
 
44
 * for example:
 
45
 *
 
46
 * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
 
47
 *
 
48
 * where buf is place to set the bits, runs is the array of b&w run
 
49
 * lengths (white then black), erun is the last run in the array, and
 
50
 * lastx is the width of the row in pixels.  Fill routines can assume
 
51
 * the run array has room for at least lastx runs and can overwrite
 
52
 * data in the run array as needed (e.g. to append zero runs to bring
 
53
 * the count up to a nice multiple).
 
54
 */
 
55
typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
 
56
 
 
57
/*
 
58
 * The default run filler; made external for other decoders.
 
59
 */
 
60
#if defined(__cplusplus)
 
61
extern "C" {
 
62
#endif
 
63
extern  void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
 
64
#if defined(__cplusplus)
 
65
}
 
66
#endif
 
67
 
 
68
 
 
69
/* finite state machine codes */
 
70
#define S_Null          0
 
71
#define S_Pass          1
 
72
#define S_Horiz         2
 
73
#define S_V0            3
 
74
#define S_VR            4
 
75
#define S_VL            5
 
76
#define S_Ext           6
 
77
#define S_TermW         7
 
78
#define S_TermB         8
 
79
#define S_MakeUpW       9
 
80
#define S_MakeUpB       10
 
81
#define S_MakeUp        11
 
82
#define S_EOL           12
 
83
 
 
84
typedef struct {                /* state table entry */
 
85
        unsigned char State;    /* see above */
 
86
        unsigned char Width;    /* width of code in bits */
 
87
        uint32  Param;          /* unsigned 32-bit run length in bits */
 
88
} TIFFFaxTabEnt;
 
89
 
 
90
extern  const TIFFFaxTabEnt TIFFFaxMainTable[];
 
91
extern  const TIFFFaxTabEnt TIFFFaxWhiteTable[];
 
92
extern  const TIFFFaxTabEnt TIFFFaxBlackTable[];
 
93
 
 
94
/*
 
95
 * The following macros define the majority of the G3/G4 decoder
 
96
 * algorithm using the state tables defined elsewhere.  To build
 
97
 * a decoder you need some setup code and some glue code. Note
 
98
 * that you may also need/want to change the way the NeedBits*
 
99
 * macros get input data if, for example, you know the data to be
 
100
 * decoded is properly aligned and oriented (doing so before running
 
101
 * the decoder can be a big performance win).
 
102
 *
 
103
 * Consult the decoder in the TIFF library for an idea of what you
 
104
 * need to define and setup to make use of these definitions.
 
105
 *
 
106
 * NB: to enable a debugging version of these macros define FAX3_DEBUG
 
107
 *     before including this file.  Trace output goes to stdout.
 
108
 */
 
109
 
 
110
#ifndef EndOfData
 
111
#define EndOfData()     (cp >= ep)
 
112
#endif
 
113
/*
 
114
 * Need <=8 or <=16 bits of input data.  Unlike viewfax we
 
115
 * cannot use/assume a word-aligned, properly bit swizzled
 
116
 * input data set because data may come from an arbitrarily
 
117
 * aligned, read-only source such as a memory-mapped file.
 
118
 * Note also that the viewfax decoder does not check for
 
119
 * running off the end of the input data buffer.  This is
 
120
 * possible for G3-encoded data because it prescans the input
 
121
 * data to count EOL markers, but can cause problems for G4
 
122
 * data.  In any event, we don't prescan and must watch for
 
123
 * running out of data since we can't permit the library to
 
124
 * scan past the end of the input data buffer.
 
125
 *
 
126
 * Finally, note that we must handle remaindered data at the end
 
127
 * of a strip specially.  The coder asks for a fixed number of
 
128
 * bits when scanning for the next code.  This may be more bits
 
129
 * than are actually present in the data stream.  If we appear
 
130
 * to run out of data but still have some number of valid bits
 
131
 * remaining then we makeup the requested amount with zeros and
 
132
 * return successfully.  If the returned data is incorrect then
 
133
 * we should be called again and get a premature EOF error;
 
134
 * otherwise we should get the right answer.
 
135
 */
 
136
#ifndef NeedBits8
 
137
#define NeedBits8(n,eoflab) do {                                        \
 
138
    if (BitsAvail < (n)) {                                              \
 
139
        if (EndOfData()) {                                              \
 
140
            if (BitsAvail == 0)                 /* no valid bits */     \
 
141
                goto eoflab;                                            \
 
142
            BitsAvail = (n);                    /* pad with zeros */    \
 
143
        } else {                                                        \
 
144
            BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;              \
 
145
            BitsAvail += 8;                                             \
 
146
        }                                                               \
 
147
    }                                                                   \
 
148
} while (0)
 
149
#endif
 
150
#ifndef NeedBits16
 
151
#define NeedBits16(n,eoflab) do {                                       \
 
152
    if (BitsAvail < (n)) {                                              \
 
153
        if (EndOfData()) {                                              \
 
154
            if (BitsAvail == 0)                 /* no valid bits */     \
 
155
                goto eoflab;                                            \
 
156
            BitsAvail = (n);                    /* pad with zeros */    \
 
157
        } else {                                                        \
 
158
            BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;              \
 
159
            if ((BitsAvail += 8) < (n)) {                               \
 
160
                if (EndOfData()) {                                      \
 
161
                    /* NB: we know BitsAvail is non-zero here */        \
 
162
                    BitsAvail = (n);            /* pad with zeros */    \
 
163
                } else {                                                \
 
164
                    BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail;      \
 
165
                    BitsAvail += 8;                                     \
 
166
                }                                                       \
 
167
            }                                                           \
 
168
        }                                                               \
 
169
    }                                                                   \
 
170
} while (0)
 
171
#endif
 
172
#define GetBits(n)      (BitAcc & ((1<<(n))-1))
 
173
#define ClrBits(n) do {                                                 \
 
174
    BitsAvail -= (n);                                                   \
 
175
    BitAcc >>= (n);                                                     \
 
176
} while (0)
 
177
 
 
178
#ifdef FAX3_DEBUG
 
179
static const char* StateNames[] = {
 
180
    "Null   ",
 
181
    "Pass   ",
 
182
    "Horiz  ",
 
183
    "V0     ",
 
184
    "VR     ",
 
185
    "VL     ",
 
186
    "Ext    ",
 
187
    "TermW  ",
 
188
    "TermB  ",
 
189
    "MakeUpW",
 
190
    "MakeUpB",
 
191
    "MakeUp ",
 
192
    "EOL    ",
 
193
};
 
194
#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
 
195
#define LOOKUP8(wid,tab,eoflab) do {                                    \
 
196
    int t;                                                              \
 
197
    NeedBits8(wid,eoflab);                                              \
 
198
    TabEnt = tab + GetBits(wid);                                        \
 
199
    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,               \
 
200
           StateNames[TabEnt->State], TabEnt->Param);                   \
 
201
    for (t = 0; t < TabEnt->Width; t++)                                 \
 
202
        DEBUG_SHOW;                                                     \
 
203
    putchar('\n');                                                      \
 
204
    fflush(stdout);                                                     \
 
205
    ClrBits(TabEnt->Width);                                             \
 
206
} while (0)
 
207
#define LOOKUP16(wid,tab,eoflab) do {                                   \
 
208
    int t;                                                              \
 
209
    NeedBits16(wid,eoflab);                                             \
 
210
    TabEnt = tab + GetBits(wid);                                        \
 
211
    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,               \
 
212
           StateNames[TabEnt->State], TabEnt->Param);                   \
 
213
    for (t = 0; t < TabEnt->Width; t++)                                 \
 
214
        DEBUG_SHOW;                                                     \
 
215
    putchar('\n');                                                      \
 
216
    fflush(stdout);                                                     \
 
217
    ClrBits(TabEnt->Width);                                             \
 
218
} while (0)
 
219
 
 
220
#define SETVAL(x) do {                                                  \
 
221
    *pa++ = RunLength + (x);                                            \
 
222
    printf("SETVAL: %d\t%d\n", RunLength + (x), a0);                    \
 
223
    a0 += x;                                                            \
 
224
    RunLength = 0;                                                      \
 
225
} while (0)
 
226
#else
 
227
#define LOOKUP8(wid,tab,eoflab) do {                                    \
 
228
    NeedBits8(wid,eoflab);                                              \
 
229
    TabEnt = tab + GetBits(wid);                                        \
 
230
    ClrBits(TabEnt->Width);                                             \
 
231
} while (0)
 
232
#define LOOKUP16(wid,tab,eoflab) do {                                   \
 
233
    NeedBits16(wid,eoflab);                                             \
 
234
    TabEnt = tab + GetBits(wid);                                        \
 
235
    ClrBits(TabEnt->Width);                                             \
 
236
} while (0)
 
237
 
 
238
/*
 
239
 * Append a run to the run length array for the
 
240
 * current row and reset decoding state.
 
241
 */
 
242
#define SETVAL(x) do {                                                  \
 
243
    *pa++ = RunLength + (x);                                            \
 
244
    a0 += (x);                                                          \
 
245
    RunLength = 0;                                                      \
 
246
} while (0)
 
247
#endif
 
248
 
 
249
/*
 
250
 * Synchronize input decoding at the start of each
 
251
 * row by scanning for an EOL (if appropriate) and
 
252
 * skipping any trash data that might be present
 
253
 * after a decoding error.  Note that the decoding
 
254
 * done elsewhere that recognizes an EOL only consumes
 
255
 * 11 consecutive zero bits.  This means that if EOLcnt
 
256
 * is non-zero then we still need to scan for the final flag
 
257
 * bit that is part of the EOL code.
 
258
 */
 
259
#define SYNC_EOL(eoflab) do {                                           \
 
260
    if (EOLcnt == 0) {                                                  \
 
261
        for (;;) {                                                      \
 
262
            NeedBits16(11,eoflab);                                      \
 
263
            if (GetBits(11) == 0)                                       \
 
264
                break;                                                  \
 
265
            ClrBits(1);                                                 \
 
266
        }                                                               \
 
267
    }                                                                   \
 
268
    for (;;) {                                                          \
 
269
        NeedBits8(8,eoflab);                                            \
 
270
        if (GetBits(8))                                                 \
 
271
            break;                                                      \
 
272
        ClrBits(8);                                                     \
 
273
    }                                                                   \
 
274
    while (GetBits(1) == 0)                                             \
 
275
        ClrBits(1);                                                     \
 
276
    ClrBits(1);                         /* EOL bit */                   \
 
277
    EOLcnt = 0;                         /* reset EOL counter/flag */    \
 
278
} while (0)
 
279
 
 
280
/*
 
281
 * Cleanup the array of runs after decoding a row.
 
282
 * We adjust final runs to insure the user buffer is not
 
283
 * overwritten and/or undecoded area is white filled.
 
284
 */
 
285
#define CLEANUP_RUNS() do {                                             \
 
286
    if (RunLength)                                                      \
 
287
        SETVAL(0);                                                      \
 
288
    if (a0 != lastx) {                                                  \
 
289
        badlength(a0, lastx);                                           \
 
290
        while (a0 > lastx && pa > thisrun)                              \
 
291
            a0 -= *--pa;                                                \
 
292
        if (a0 < lastx) {                                               \
 
293
            if (a0 < 0)                                                 \
 
294
                a0 = 0;                                                 \
 
295
            if ((pa-thisrun)&1)                                         \
 
296
                SETVAL(0);                                              \
 
297
            SETVAL(lastx - a0);                                         \
 
298
        } else if (a0 > lastx) {                                        \
 
299
            SETVAL(lastx);                                              \
 
300
            SETVAL(0);                                                  \
 
301
        }                                                               \
 
302
    }                                                                   \
 
303
} while (0)
 
304
 
 
305
/*
 
306
 * Decode a line of 1D-encoded data.
 
307
 *
 
308
 * The line expanders are written as macros so that they can be reused
 
309
 * but still have direct access to the local variables of the "calling"
 
310
 * function.
 
311
 *
 
312
 * Note that unlike the original version we have to explicitly test for
 
313
 * a0 >= lastx after each black/white run is decoded.  This is because
 
314
 * the original code depended on the input data being zero-padded to
 
315
 * insure the decoder recognized an EOL before running out of data.
 
316
 */
 
317
#define EXPAND1D(eoflab) do {                                           \
 
318
    for (;;) {                                                          \
 
319
        for (;;) {                                                      \
 
320
            LOOKUP16(12, TIFFFaxWhiteTable, eof1d);                     \
 
321
            switch (TabEnt->State) {                                    \
 
322
            case S_EOL:                                                 \
 
323
                EOLcnt = 1;                                             \
 
324
                goto done1d;                                            \
 
325
            case S_TermW:                                               \
 
326
                SETVAL(TabEnt->Param);                                  \
 
327
                goto doneWhite1d;                                       \
 
328
            case S_MakeUpW:                                             \
 
329
            case S_MakeUp:                                              \
 
330
                a0 += TabEnt->Param;                                    \
 
331
                RunLength += TabEnt->Param;                             \
 
332
                break;                                                  \
 
333
            default:                                                    \
 
334
                unexpected("WhiteTable", a0);                           \
 
335
                goto done1d;                                            \
 
336
            }                                                           \
 
337
        }                                                               \
 
338
    doneWhite1d:                                                        \
 
339
        if (a0 >= lastx)                                                \
 
340
            goto done1d;                                                \
 
341
        for (;;) {                                                      \
 
342
            LOOKUP16(13, TIFFFaxBlackTable, eof1d);                     \
 
343
            switch (TabEnt->State) {                                    \
 
344
            case S_EOL:                                                 \
 
345
                EOLcnt = 1;                                             \
 
346
                goto done1d;                                            \
 
347
            case S_TermB:                                               \
 
348
                SETVAL(TabEnt->Param);                                  \
 
349
                goto doneBlack1d;                                       \
 
350
            case S_MakeUpB:                                             \
 
351
            case S_MakeUp:                                              \
 
352
                a0 += TabEnt->Param;                                    \
 
353
                RunLength += TabEnt->Param;                             \
 
354
                break;                                                  \
 
355
            default:                                                    \
 
356
                unexpected("BlackTable", a0);                           \
 
357
                goto done1d;                                            \
 
358
            }                                                           \
 
359
        }                                                               \
 
360
    doneBlack1d:                                                        \
 
361
        if (a0 >= lastx)                                                \
 
362
            goto done1d;                                                \
 
363
        if( *(pa-1) == 0 && *(pa-2) == 0 )                              \
 
364
            pa -= 2;                                                    \
 
365
    }                                                                   \
 
366
eof1d:                                                                  \
 
367
    prematureEOF(a0);                                                   \
 
368
    CLEANUP_RUNS();                                                     \
 
369
    goto eoflab;                                                        \
 
370
done1d:                                                                 \
 
371
    CLEANUP_RUNS();                                                     \
 
372
} while (0)
 
373
 
 
374
/*
 
375
 * Update the value of b1 using the array
 
376
 * of runs for the reference line.
 
377
 */
 
378
#define CHECK_b1 do {                                                   \
 
379
    if (pa != thisrun) while (b1 <= a0 && b1 < lastx) {                 \
 
380
        b1 += pb[0] + pb[1];                                            \
 
381
        pb += 2;                                                        \
 
382
    }                                                                   \
 
383
} while (0)
 
384
 
 
385
/*
 
386
 * Expand a row of 2D-encoded data.
 
387
 */
 
388
#define EXPAND2D(eoflab) do {                                           \
 
389
    while (a0 < lastx) {                                                \
 
390
        LOOKUP8(7, TIFFFaxMainTable, eof2d);                            \
 
391
        switch (TabEnt->State) {                                        \
 
392
        case S_Pass:                                                    \
 
393
            CHECK_b1;                                                   \
 
394
            b1 += *pb++;                                                \
 
395
            RunLength += b1 - a0;                                       \
 
396
            a0 = b1;                                                    \
 
397
            b1 += *pb++;                                                \
 
398
            break;                                                      \
 
399
        case S_Horiz:                                                   \
 
400
            if ((pa-thisrun)&1) {                                       \
 
401
                for (;;) {      /* black first */                       \
 
402
                    LOOKUP16(13, TIFFFaxBlackTable, eof2d);             \
 
403
                    switch (TabEnt->State) {                            \
 
404
                    case S_TermB:                                       \
 
405
                        SETVAL(TabEnt->Param);                          \
 
406
                        goto doneWhite2da;                              \
 
407
                    case S_MakeUpB:                                     \
 
408
                    case S_MakeUp:                                      \
 
409
                        a0 += TabEnt->Param;                            \
 
410
                        RunLength += TabEnt->Param;                     \
 
411
                        break;                                          \
 
412
                    default:                                            \
 
413
                        goto badBlack2d;                                \
 
414
                    }                                                   \
 
415
                }                                                       \
 
416
            doneWhite2da:;                                              \
 
417
                for (;;) {      /* then white */                        \
 
418
                    LOOKUP16(12, TIFFFaxWhiteTable, eof2d);             \
 
419
                    switch (TabEnt->State) {                            \
 
420
                    case S_TermW:                                       \
 
421
                        SETVAL(TabEnt->Param);                          \
 
422
                        goto doneBlack2da;                              \
 
423
                    case S_MakeUpW:                                     \
 
424
                    case S_MakeUp:                                      \
 
425
                        a0 += TabEnt->Param;                            \
 
426
                        RunLength += TabEnt->Param;                     \
 
427
                        break;                                          \
 
428
                    default:                                            \
 
429
                        goto badWhite2d;                                \
 
430
                    }                                                   \
 
431
                }                                                       \
 
432
            doneBlack2da:;                                              \
 
433
            } else {                                                    \
 
434
                for (;;) {      /* white first */                       \
 
435
                    LOOKUP16(12, TIFFFaxWhiteTable, eof2d);             \
 
436
                    switch (TabEnt->State) {                            \
 
437
                    case S_TermW:                                       \
 
438
                        SETVAL(TabEnt->Param);                          \
 
439
                        goto doneWhite2db;                              \
 
440
                    case S_MakeUpW:                                     \
 
441
                    case S_MakeUp:                                      \
 
442
                        a0 += TabEnt->Param;                            \
 
443
                        RunLength += TabEnt->Param;                     \
 
444
                        break;                                          \
 
445
                    default:                                            \
 
446
                        goto badWhite2d;                                \
 
447
                    }                                                   \
 
448
                }                                                       \
 
449
            doneWhite2db:;                                              \
 
450
                for (;;) {      /* then black */                        \
 
451
                    LOOKUP16(13, TIFFFaxBlackTable, eof2d);             \
 
452
                    switch (TabEnt->State) {                            \
 
453
                    case S_TermB:                                       \
 
454
                        SETVAL(TabEnt->Param);                          \
 
455
                        goto doneBlack2db;                              \
 
456
                    case S_MakeUpB:                                     \
 
457
                    case S_MakeUp:                                      \
 
458
                        a0 += TabEnt->Param;                            \
 
459
                        RunLength += TabEnt->Param;                     \
 
460
                        break;                                          \
 
461
                    default:                                            \
 
462
                        goto badBlack2d;                                \
 
463
                    }                                                   \
 
464
                }                                                       \
 
465
            doneBlack2db:;                                              \
 
466
            }                                                           \
 
467
            CHECK_b1;                                                   \
 
468
            break;                                                      \
 
469
        case S_V0:                                                      \
 
470
            CHECK_b1;                                                   \
 
471
            SETVAL(b1 - a0);                                            \
 
472
            b1 += *pb++;                                                \
 
473
            break;                                                      \
 
474
        case S_VR:                                                      \
 
475
            CHECK_b1;                                                   \
 
476
            SETVAL(b1 - a0 + TabEnt->Param);                            \
 
477
            b1 += *pb++;                                                \
 
478
            break;                                                      \
 
479
        case S_VL:                                                      \
 
480
            CHECK_b1;                                                   \
 
481
            SETVAL(b1 - a0 - TabEnt->Param);                            \
 
482
            b1 -= *--pb;                                                \
 
483
            break;                                                      \
 
484
        case S_Ext:                                                     \
 
485
            *pa++ = lastx - a0;                                         \
 
486
            extension(a0);                                              \
 
487
            goto eol2d;                                                 \
 
488
        case S_EOL:                                                     \
 
489
            *pa++ = lastx - a0;                                         \
 
490
            NeedBits8(4,eof2d);                                         \
 
491
            if (GetBits(4))                                             \
 
492
                unexpected("EOL", a0);                                  \
 
493
            ClrBits(4);                                                 \
 
494
            EOLcnt = 1;                                                 \
 
495
            goto eol2d;                                                 \
 
496
        default:                                                        \
 
497
        badMain2d:                                                      \
 
498
            unexpected("MainTable", a0);                                \
 
499
            goto eol2d;                                                 \
 
500
        badBlack2d:                                                     \
 
501
            unexpected("BlackTable", a0);                               \
 
502
            goto eol2d;                                                 \
 
503
        badWhite2d:                                                     \
 
504
            unexpected("WhiteTable", a0);                               \
 
505
            goto eol2d;                                                 \
 
506
        eof2d:                                                          \
 
507
            prematureEOF(a0);                                           \
 
508
            CLEANUP_RUNS();                                             \
 
509
            goto eoflab;                                                \
 
510
        }                                                               \
 
511
    }                                                                   \
 
512
    if (RunLength) {                                                    \
 
513
        if (RunLength + a0 < lastx) {                                   \
 
514
            /* expect a final V0 */                                     \
 
515
            NeedBits8(1,eof2d);                                         \
 
516
            if (!GetBits(1))                                            \
 
517
                goto badMain2d;                                         \
 
518
            ClrBits(1);                                                 \
 
519
        }                                                               \
 
520
        SETVAL(0);                                                      \
 
521
    }                                                                   \
 
522
eol2d:                                                                  \
 
523
    CLEANUP_RUNS();                                                     \
 
524
} while (0)
 
525
#endif /* _FAX3_ */