Back to index

im-sdk  12.3.91
FrameMgr.c
Go to the documentation of this file.
00001 /******************************************************************
00002 Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts,
00003 
00004                         All Rights Reserved
00005 
00006 Permission to use, copy, modify, and distribute this software and its 
00007 documentation for any purpose and without fee is hereby granted, 
00008 provided that the above copyright notice appear in all copies and that
00009 both that copyright notice and this permission notice appear in 
00010 supporting documentation, and that the names of Digital or MIT not be
00011 used in advertising or publicity pertaining to distribution of the
00012 software without specific, written prior permission.  
00013 
00014 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00015 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00016 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00017 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00018 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00019 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00020 SOFTWARE.
00021 
00022   Author: Hiroyuki Miyamoto  Digital Equipment Corporation
00023                              miyamoto@jrd.dec.com
00024 ******************************************************************/
00025 
00026 #include <X11/Xlibint.h>
00027 #include "FrameMgr.h"
00028 
00029 /* Convenient macro */
00030 
00031 #define _UNIT(n)   ((int)(n) & 0xff)
00032 #define _NUMBER(n) (((int)(n) >> 8) & 0xff)
00033 
00034 /* For byte swapping */
00035 
00036 #define Swap16(p, n) ((p)->byte_swap ?       \
00037                     (((n) << 8 & 0xff00) | \
00038                      ((n) >> 8 & 0xff)     \
00039                     ) : n)
00040 #define Swap32(p, n) ((p)->byte_swap ?            \
00041                     (((n) << 24 & 0xff000000) | \
00042                      ((n) <<  8 & 0xff0000) |   \
00043                      ((n) >>  8 & 0xff00) |     \
00044                      ((n) >> 24 & 0xff)         \
00045                     ) : n)
00046 
00047 /* Type definition */
00048 
00049 typedef struct _Iter *Iter;
00050 
00051 typedef struct _FrameInst *FrameInst;
00052 
00053 typedef union {
00054     int num;         /* For BARRAY */
00055     FrameInst fi;    /* For POINTER */
00056     Iter iter;              /* For ITER */
00057 } ExtraDataRec, *ExtraData;
00058 
00059 typedef struct _Chain {
00060        ExtraDataRec d;
00061        int frame_no;
00062        struct _Chain *next;
00063 } ChainRec, *Chain;
00064 
00065 typedef struct _ChainMgr {
00066     Chain top;
00067     Chain tail;
00068 } ChainMgrRec, *ChainMgr;
00069 
00070 typedef struct _ChainIter {
00071     Chain cur;
00072 } ChainIterRec, *ChainIter;
00073 
00074 typedef struct _FrameIter {
00075     Iter iter;
00076     Bool counting;
00077     unsigned int counter;
00078     int end;
00079     struct _FrameIter* next;
00080 } FrameIterRec, *FrameIter;
00081 
00082 typedef struct _FrameInst {
00083     XimFrame template;
00084     ChainMgrRec cm;
00085     int cur_no;
00086 } FrameInstRec;
00087 
00088 typedef void  (*IterStartWatchProc)(
00089                                 Iter it, void* client_data
00090                                 );
00091 
00092 typedef struct _Iter {
00093     XimFrame template;
00094     int max_count;
00095     Bool allow_expansion;
00096     ChainMgrRec cm;
00097     int cur_no;
00098     IterStartWatchProc start_watch_proc;
00099     void* client_data;
00100     Bool start_counter;
00101 } IterRec;
00102 
00103 typedef struct _FrameMgr {
00104     XimFrame frame;
00105     FrameInst fi;
00106     char* area;
00107     int idx;
00108     Bool byte_swap;
00109     int total_size;
00110     FrameIter iters;
00111 } FrameMgrRec;
00112 
00113 typedef union {
00114     int num;          /* For BARRAY and PAD */
00115     struct {          /* For COUNTER_* */
00116        Iter iter;        
00117        Bool is_byte_len;
00118     } counter;
00119 } XimFrameTypeInfoRec, *XimFrameTypeInfo;
00120 
00121 /* Special values */
00122 #define NO_VALUE -1
00123 #define NO_VALID_FIELD -2
00124 
00125 static FrameInst FrameInstInit(XimFrame frame);
00126 static void FrameInstFree(FrameInst fi);
00127 static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info);
00128 static XimFrameType FrameInstPeekNextType(FrameInst fi, XimFrameTypeInfo info);
00129 static FmStatus FrameInstSetSize(FrameInst fi, int num);
00130 static FmStatus FrameInstSetIterCount(FrameInst fi, int num);
00131 static int FrameInstGetTotalSize(FrameInst fi);
00132 static void FrameInstReset(FrameInst fi);
00133 
00134 static Iter IterInit(XimFrame frame, int count);
00135 static void IterFree(Iter it);
00136 static int FrameInstGetSize(FrameInst fi);
00137 static int IterGetSize(Iter it);
00138 static XimFrameType IterGetNextType(Iter it, XimFrameTypeInfo info);
00139 static XimFrameType IterPeekNextType(Iter it, XimFrameTypeInfo info);
00140 static FmStatus IterSetSize(Iter it, int num);
00141 static FmStatus IterSetIterCount(Iter it, int num);
00142 static int IterGetTotalSize(Iter it);
00143 static void IterReset(Iter it);
00144 static Bool IterIsLoopEnd(Iter it, Bool* myself);
00145 static void IterSetStartWatch(Iter it, IterStartWatchProc proc, void* client_data);
00146 static void _IterStartWatch(Iter it, void* client_data);
00147 
00148 static ExtraData ChainMgrGetExtraData(ChainMgr cm, int frame_no);
00149 static ExtraData ChainMgrSetData(ChainMgr cm, int frame_no,
00150                              ExtraDataRec data);
00151 static Bool ChainIterGetNext(ChainIter ci, int* frame_no, ExtraData d);
00152 static int _FrameInstIncrement(XimFrame frame, int count);
00153 static int _FrameInstDecrement(XimFrame frame, int count);
00154 static int _FrameInstGetItemSize(FrameInst fi, int cur_no);
00155 static Bool FrameInstIsIterLoopEnd(FrameInst fi);
00156 
00157 static FrameIter _FrameMgrAppendIter(FrameMgr fm, Iter it, int end);
00158 static FrameIter _FrameIterCounterIncr(FrameIter fitr, int i);
00159 static void _FrameMgrRemoveIter(FrameMgr fm, FrameIter it);
00160 static Bool _FrameMgrIsIterLoopEnd(FrameMgr fm);
00161 static Bool _FrameMgrProcessPadding(FrameMgr fm, FmStatus* status);
00162 
00163 #define IterGetIterCount(it) ((it)->allow_expansion ? \
00164                            NO_VALUE : (it)->max_count)
00165 
00166 #define IterFixIteration(it) ((it)->allow_expansion = False)
00167 
00168 #define IterSetStarter(it) ((it)->start_counter = True)
00169 
00170 #define ChainMgrInit(cm) (cm)->top = (cm)->tail = NULL
00171 #define ChainMgrFree(cm) {\
00172     Chain tmp, cur = (cm)->top;\
00173 \
00174     while (cur) {\
00175        tmp = cur->next;\
00176        Xfree(cur);\
00177        cur = tmp;\
00178     }\
00179 }
00180 #define ChainIterInit(ci, cm) {\
00181     (ci)->cur = (cm)->top;\
00182 }
00183 /* ChainIterFree has nothing to do. */
00184 #define ChainIterFree(ci)
00185 
00186 #define FrameInstIsEnd(fi) ((fi)->template[(fi)->cur_no].type == EOL)
00187 
00188 FrameMgr FrameMgrInit(XimFrame frame, char* area, Bool byte_swap)
00189 {
00190     FrameMgr fm;
00191 
00192     fm = (FrameMgr)Xmalloc(sizeof(FrameMgrRec));
00193 
00194     fm->frame = frame;
00195     fm->fi = FrameInstInit(frame);
00196     fm->area = (char *)area;
00197     fm->idx = 0;
00198     fm->byte_swap = byte_swap;
00199     fm->total_size = NO_VALUE;
00200     fm->iters = NULL;
00201 
00202     return fm;
00203 }
00204 
00205 void FrameMgrInitWithData(FrameMgr fm, XimFrame frame, void* area,
00206                        Bool byte_swap)
00207 {
00208     fm->frame = frame;
00209     fm->fi = FrameInstInit(frame);
00210     fm->area = (char *)area;
00211     fm->idx = 0;
00212     fm->byte_swap = byte_swap;
00213     fm->total_size = NO_VALUE;
00214 }
00215 
00216 void FrameMgrFree(FrameMgr fm)
00217 {
00218     FrameInstFree(fm->fi);
00219     Xfree(fm);
00220 }
00221 
00222 FmStatus FrameMgrSetBuffer(FrameMgr fm, void* area)
00223 {
00224     if (fm->area) {
00225        return FmBufExist;
00226     }
00227     fm->area = (char *)area;
00228     return FmSuccess;
00229 }
00230 
00231 FmStatus _FrameMgrPutToken(FrameMgr fm, void* data, int data_size)
00232 {
00233     XimFrameType type;
00234     XimFrameTypeInfoRec info;
00235 
00236     if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size)
00237        return FmNoMoreData;
00238 
00239     type = FrameInstGetNextType(fm->fi, &info);
00240 
00241     if (type & COUNTER_MASK) {
00242        unsigned long input_length;
00243 
00244        if (info.counter.is_byte_len) {
00245            if ((input_length = IterGetTotalSize(info.counter.iter))
00246               == NO_VALUE) {
00247               return FmCannotCalc;
00248            }
00249        } else {
00250            if ((input_length = IterGetIterCount(info.counter.iter))
00251               == NO_VALUE) {
00252               return FmCannotCalc;
00253            }
00254        }
00255        if (type == COUNTER_BIT8) {
00256            *(CARD8*)(fm->area + fm->idx) = input_length;
00257            fm->idx++;
00258        } else if (type == COUNTER_BIT16) {
00259            *(CARD16*)(fm->area + fm->idx) = Swap16(fm, input_length);
00260            fm->idx += 2;
00261        } else if (type == COUNTER_BIT32) {
00262            *(CARD32*)(fm->area + fm->idx) = Swap32(fm, input_length);
00263            fm->idx += 4;
00264        }
00265        _FrameMgrPutToken(fm, data, data_size);
00266        return FmSuccess;
00267     }
00268 
00269     if (type == BIT8) {
00270        if (data_size == sizeof(unsigned char)) {
00271            unsigned long num = *(unsigned char*)data;
00272            *(CARD8*)(fm->area + fm->idx) = num;
00273        } else if (data_size == sizeof(unsigned short)) {
00274            unsigned long num = *(unsigned short*)data;
00275            *(CARD8*)(fm->area + fm->idx) = num;
00276        } else if (data_size == sizeof(unsigned int)) {
00277            unsigned long num = *(unsigned int*)data;
00278            *(CARD8*)(fm->area + fm->idx) = num;
00279        } else if (data_size == sizeof(unsigned long)) {
00280            unsigned long num = *(unsigned long*)data;
00281            *(CARD8*)(fm->area + fm->idx) = num;
00282        } else {
00283            ;/* Should never reached */
00284        }
00285        fm->idx++;
00286        return FmSuccess;
00287     } else if (type == BIT16) {
00288        if (data_size == sizeof(unsigned char)) {
00289            unsigned long num = *(unsigned char*)data;
00290            *(CARD16*)(fm->area + fm->idx) = Swap16(fm, num);
00291        } else if (data_size == sizeof(unsigned short)) {
00292            unsigned long num = *(unsigned short*)data;
00293            *(CARD16*)(fm->area + fm->idx) = Swap16(fm, num);
00294        } else if (data_size == sizeof(unsigned int)) {
00295            unsigned long num = *(unsigned int*)data;
00296            *(CARD16*)(fm->area + fm->idx) = Swap16(fm, num);
00297        } else if (data_size == sizeof(unsigned long)) {
00298            unsigned long num = *(unsigned long*)data;
00299            *(CARD16*)(fm->area + fm->idx) = Swap16(fm, num);
00300        } else {
00301            ;/* Should never reached */
00302        }
00303        fm->idx += 2;
00304        return FmSuccess;
00305     } else if (type == BIT32) {
00306        if (data_size == sizeof(unsigned char)) {
00307            unsigned long num = *(unsigned char*)data;
00308            *(CARD32*)(fm->area + fm->idx) = Swap32(fm, num);
00309        } else if (data_size == sizeof(unsigned short)) {
00310            unsigned long num = *(unsigned short*)data;
00311            *(CARD32*)(fm->area + fm->idx) = Swap32(fm, num);
00312        } else if (data_size == sizeof(unsigned int)) {
00313            unsigned long num = *(unsigned int*)data;
00314            *(CARD32*)(fm->area + fm->idx) = Swap32(fm, num);
00315        } else if (data_size == sizeof(unsigned long)) {
00316            unsigned long num = *(unsigned long*)data;
00317            *(CARD32*)(fm->area + fm->idx) = Swap32(fm, num);
00318        } else {
00319            ;/* Should never reached */
00320        }
00321        fm->idx += 4;
00322        return FmSuccess;
00323     }
00324      else if (type == BARRAY && info.num != NO_VALUE) {
00325        if (info.num > 0) {
00326            bcopy(*(char**)data, fm->area + fm->idx, info.num);
00327            fm->idx += info.num;
00328        }
00329        return FmSuccess;
00330     } else if (type == BARRAY && info.num == NO_VALUE) {
00331        return FmInvalidCall;
00332     } else if (type == PADDING && info.num != NO_VALUE) {
00333         fm->idx += info.num;
00334        return _FrameMgrPutToken(fm, data, data_size);
00335     } else if (type == PADDING && info.num == NO_VALUE) {
00336         return FmInvalidCall;
00337     } else if (type == ITER) {
00338        return FmInvalidCall;
00339     } else if (type == EOL) {
00340        return FmEOD;
00341     } else {
00342        ; /* Should never be reached */
00343     }
00344     return FmInvalidCall;
00345 }
00346 
00347 FmStatus _FrameMgrGetToken(FrameMgr fm , void* data, int data_size)
00348 {
00349     XimFrameType type;
00350     static XimFrameTypeInfoRec info; /* memory */
00351     FrameIter fitr;
00352 
00353     if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size)
00354        return FmNoMoreData;
00355 
00356     type = FrameInstGetNextType(fm->fi, &info);
00357 
00358     if (type & COUNTER_MASK) {
00359        int end = 0;
00360        FrameIter client_data;
00361 
00362        type &= ~COUNTER_MASK;
00363        if (type == BIT8) {
00364            end = *(CARD8*)(fm->area + fm->idx);
00365        }
00366        else if (type == BIT16) {
00367            end = Swap16(fm, *(CARD16*)(fm->area + fm->idx));
00368        }
00369        else if (type == BIT32) {
00370            end = Swap32(fm, *(CARD32*)(fm->area + fm->idx));
00371        }
00372        if ((client_data = _FrameMgrAppendIter(fm, info.counter.iter, end))) {
00373            IterSetStarter(info.counter.iter);
00374            IterSetStartWatch(info.counter.iter, 
00375                            _IterStartWatch, (void*)client_data);
00376        }
00377     }
00378 
00379     type &= ~COUNTER_MASK;
00380     if (type == BIT8) {
00381        if (data_size == sizeof(unsigned char)) {
00382            *(unsigned char*)data = *(CARD8*)(fm->area + fm->idx);
00383        } else if (data_size == sizeof(unsigned short)) {
00384            *(unsigned short*)data = *(CARD8*)(fm->area + fm->idx);
00385        } else if (data_size == sizeof(unsigned int)) {
00386            *(unsigned int*)data = *(CARD8*)(fm->area + fm->idx);
00387        } else if (data_size == sizeof(unsigned long)) {
00388            *(unsigned long*)data = *(CARD8*)(fm->area + fm->idx);
00389        } else {
00390            ;/* Should never reached */
00391        }
00392        fm->idx++;
00393        if ((fitr = _FrameIterCounterIncr(fm->iters, 1/*BIT8*/))) {
00394            _FrameMgrRemoveIter(fm, fitr);
00395        }
00396        return FmSuccess;
00397     } else if (type == BIT16) {
00398        if (data_size == sizeof(unsigned char)) {
00399            *(unsigned char*)data =
00400               Swap16(fm, *(CARD16*)(fm->area + fm->idx));
00401        } else if (data_size == sizeof(unsigned short)) {
00402            *(unsigned short*)data =
00403               Swap16(fm, *(CARD16*)(fm->area + fm->idx));
00404        } else if (data_size == sizeof(unsigned int)) {
00405            *(unsigned int*)data =
00406               Swap16(fm, *(CARD16*)(fm->area + fm->idx));
00407        } else if (data_size == sizeof(unsigned long)) {
00408            *(unsigned long*)data =
00409               Swap16(fm, *(CARD16*)(fm->area + fm->idx));
00410        } else {
00411            ;/* Should never reached */
00412        }
00413        fm->idx += 2;
00414        if ((fitr = _FrameIterCounterIncr(fm->iters, 2/*BIT16*/))) {
00415            _FrameMgrRemoveIter(fm, fitr);
00416        }
00417        return FmSuccess;
00418     } else if (type == BIT32) {
00419        if (data_size == sizeof(unsigned char)) {
00420            *(unsigned char*)data =
00421               Swap32(fm, *(CARD32*)(fm->area + fm->idx));
00422        } else if (data_size == sizeof(unsigned short)) {
00423            *(unsigned short*)data =
00424               Swap32(fm, *(CARD32*)(fm->area + fm->idx));
00425        } else if (data_size == sizeof(unsigned int)) {
00426            *(unsigned int*)data =
00427               Swap32(fm, *(CARD32*)(fm->area + fm->idx));
00428        } else if (data_size == sizeof(unsigned long)) {
00429            *(unsigned long*)data =
00430               Swap32(fm, *(CARD32*)(fm->area + fm->idx));
00431        } else {
00432            ;/* Should never reached */
00433        }
00434        fm->idx += 4;
00435        if ((fitr = _FrameIterCounterIncr(fm->iters, 4/*BIT32*/))) {
00436            _FrameMgrRemoveIter(fm, fitr);
00437        }
00438        return FmSuccess;
00439     }
00440       else if (type == BARRAY && info.num != NO_VALUE) {
00441        if (info.num > 0) {
00442            *(char**)data = fm->area + fm->idx;
00443            fm->idx += info.num;
00444            if ((fitr = _FrameIterCounterIncr(fm->iters, info.num))) {
00445               _FrameMgrRemoveIter(fm, fitr);
00446            }
00447        } else {
00448            *(char**)data = NULL;
00449        }
00450        return FmSuccess;
00451     } else if (type == BARRAY && info.num == NO_VALUE) {
00452        return FmInvalidCall;
00453     } else if (type == PADDING && info.num != NO_VALUE) {
00454         fm->idx += info.num;
00455        if ((fitr = _FrameIterCounterIncr(fm->iters, info.num))) {
00456            _FrameMgrRemoveIter(fm, fitr);
00457        }
00458        return _FrameMgrGetToken(fm, data, data_size);
00459     } else if (type == PADDING && info.num == NO_VALUE) {
00460         return FmInvalidCall;
00461     } else if (type == ITER) {
00462        return FmInvalidCall;       /* if comes here, it's a bug! */
00463     } else if (type == EOL) {
00464        return FmEOD;
00465     } else {
00466        ; /* Should never be reached */
00467     }
00468     return FmInvalidCall;
00469 }
00470 
00471 
00472 FmStatus FrameMgrSetSize(FrameMgr fm, int barray_size)
00473 {
00474     if (FrameInstSetSize(fm->fi, barray_size) == FmSuccess)
00475        return FmSuccess;
00476     else
00477        return FmNoMoreData;
00478 }
00479 
00480 
00481 FmStatus FrameMgrSetIterCount(FrameMgr fm, int count)
00482 {
00483     if (FrameInstSetIterCount(fm->fi, count) == FmSuccess)
00484        return FmSuccess;
00485     else
00486        return FmNoMoreData;
00487 }
00488 
00489 
00490 FmStatus FrameMgrSetTotalSize(FrameMgr fm, int total_size)
00491 {
00492     fm->total_size = total_size;
00493     return FmSuccess;
00494 }
00495 
00496 
00497 int FrameMgrGetTotalSize(FrameMgr fm)
00498 {
00499     return FrameInstGetTotalSize(fm->fi);
00500 }
00501 
00502 
00503 int FrameMgrGetSize(FrameMgr fm)
00504 {
00505     register int ret_size;
00506 
00507     ret_size = FrameInstGetSize(fm->fi);
00508     if (ret_size == NO_VALID_FIELD)
00509        return NO_VALUE;
00510 
00511     return ret_size;
00512 }
00513 
00514 
00515 FmStatus FrameMgrSkipToken(FrameMgr fm, int skip_count)
00516 {
00517     XimFrameType type;
00518     XimFrameTypeInfoRec info;
00519     register int i;
00520 
00521     if (fm->total_size != NO_VALUE && fm->idx >= fm->total_size)
00522        return FmNoMoreData;
00523 
00524     for (i = 0; i < skip_count; i++) {
00525        type = FrameInstGetNextType(fm->fi, &info);
00526        type &= ~COUNTER_MASK;
00527 
00528        if (type == BIT8) {
00529            fm->idx++;
00530        } else if (type == BIT16) {
00531            fm->idx += 2;
00532        } else if (type == BIT32) {
00533            fm->idx += 4;
00534        }
00535          else if (type == BARRAY && info.num != NO_VALUE) {
00536            fm->idx += info.num;
00537        } else if (type == BARRAY && info.num == NO_VALUE) {
00538            return FmInvalidCall;
00539        } else if (type == PADDING && info.num != NO_VALUE) {
00540            fm->idx += info.num;
00541            return FrameMgrSkipToken(fm, skip_count);
00542        } else if (type == PADDING && info.num == NO_VALUE) {
00543            return FmInvalidCall;
00544        } else if (type == ITER) {
00545            return FmInvalidCall;
00546        } else if (type == EOL) {
00547            return FmEOD;
00548        } else {
00549            ; /* Should never be reached */
00550        }
00551     }
00552     return FmSuccess;
00553 }
00554 
00555 
00556 void FrameMgrReset(FrameMgr fm)
00557 {
00558     fm->idx = 0;
00559     FrameInstReset(fm->fi);
00560 }
00561 
00562 
00563 Bool FrameMgrIsIterLoopEnd(FrameMgr fm, FmStatus* status)
00564 {
00565     do {
00566        if (_FrameMgrIsIterLoopEnd(fm)) {
00567            return(True);
00568        }
00569     } while (_FrameMgrProcessPadding(fm, status));
00570     
00571     return(False);
00572 }
00573 
00574 
00575 /* Internal routines */
00576 
00577 static Bool _FrameMgrIsIterLoopEnd(FrameMgr fm)
00578 {
00579     return(FrameInstIsIterLoopEnd(fm->fi));
00580 }
00581 
00582 
00583 static Bool _FrameMgrProcessPadding(FrameMgr fm, FmStatus* status)
00584 {
00585     XimFrameTypeInfoRec info;
00586     XimFrameType next_type = FrameInstPeekNextType(fm->fi, &info);
00587     FrameIter fitr;
00588 
00589     if ((next_type == PADDING) && (info.num != NO_VALUE)) {
00590         next_type = FrameInstGetNextType(fm->fi, &info);
00591         fm->idx += info.num;
00592        if ((fitr = _FrameIterCounterIncr(fm->iters, info.num))) {
00593            _FrameMgrRemoveIter(fm, fitr);
00594        }
00595        *status = FmSuccess;
00596        return(True);
00597     } 
00598     else if ((next_type == PADDING) && (info.num == NO_VALUE)) {
00599        *status = FmInvalidCall;
00600        return(True);
00601     }
00602     else {
00603        *status = FmSuccess;
00604        return(False);
00605     }
00606 }
00607 
00608 
00609 static FrameInst FrameInstInit(XimFrame frame)
00610 {
00611     FrameInst fi;
00612 
00613     fi= (FrameInst)Xmalloc(sizeof(FrameInstRec));
00614 
00615     fi->template = frame;
00616     fi->cur_no = 0;
00617     ChainMgrInit(&fi->cm);
00618     return fi;
00619 }
00620 
00621 static void FrameInstFree(FrameInst fi)
00622 {
00623     ChainIterRec ci;
00624     int frame_no;
00625     ExtraDataRec d;
00626 
00627     ChainIterInit(&ci, &fi->cm);
00628 
00629     while (ChainIterGetNext(&ci, &frame_no, &d)) {
00630        register XimFrameType type;
00631        type = fi->template[frame_no].type;
00632        if (type == ITER) {
00633            if (d.iter)
00634               IterFree(d.iter);
00635        } else if (type == POINTER) {
00636            if (d.fi)
00637               FrameInstFree(d.fi);
00638        }
00639     }
00640     ChainIterFree(&ci);
00641     ChainMgrFree(&fi->cm);
00642     Xfree(fi);
00643 }
00644 
00645 static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info)
00646 {
00647     XimFrameType ret_type;
00648 
00649     ret_type = fi->template[fi->cur_no].type;
00650 
00651     switch (ret_type) {
00652       case BIT8 :
00653       case BIT16 :
00654       case BIT32 :
00655       case EOL :
00656        fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00657        break;
00658 
00659       case COUNTER_BIT8 :
00660       case COUNTER_BIT16 :
00661       case COUNTER_BIT32 :
00662        if (info) {
00663            register int offset, iter_idx;
00664 
00665            info->counter.is_byte_len = 
00666               ((int)fi->template[fi->cur_no].data & 0xff) == FmCounterByte;
00667            offset = (int)fi->template[fi->cur_no].data >> 8;
00668            iter_idx = fi->cur_no + offset;
00669            if (fi->template[iter_idx].type == ITER) {
00670               ExtraData d;
00671               ExtraDataRec dr;
00672 
00673               if ((d = ChainMgrGetExtraData(&fi->cm, iter_idx)) == NULL) {
00674                   dr.iter = IterInit(&fi->template[iter_idx + 1], NO_VALUE);
00675                   d = ChainMgrSetData(&fi->cm, iter_idx, dr);
00676               }
00677               info->counter.iter = d->iter;
00678            } else {
00679               /* Should not be reached here */
00680            }
00681        }
00682        fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00683        break;
00684 
00685       case BARRAY :
00686        if (info) {
00687            ExtraData d;
00688 
00689            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00690               info->num = NO_VALUE;
00691            } else {
00692               info->num = d->num;
00693            }
00694        }
00695        fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00696        break;
00697 
00698       case PADDING :
00699        if (info) {
00700            register int unit, number, size, i;
00701 
00702            unit = _UNIT(fi->template[fi->cur_no].data);
00703            number = _NUMBER(fi->template[fi->cur_no].data);
00704            
00705            i = fi->cur_no;
00706            size = 0;
00707            while (number > 0) {
00708                i = _FrameInstDecrement(fi->template, i);
00709               size += _FrameInstGetItemSize(fi, i);
00710               number--;
00711            }
00712            info->num = (unit - (size % unit)) % unit;
00713        }
00714        fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00715        break;
00716        
00717       case ITER :
00718        {
00719            ExtraData d;
00720            ExtraDataRec dr;
00721            XimFrameType sub_type;
00722 
00723 
00724            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00725               dr.iter = IterInit(&fi->template[fi->cur_no + 1], NO_VALUE);
00726               d = ChainMgrSetData(&fi->cm, fi->cur_no, dr);
00727            }
00728            sub_type = IterGetNextType(d->iter, info);
00729            if (sub_type == EOL) {
00730               fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00731               ret_type = FrameInstGetNextType(fi, info);
00732            } else {
00733               ret_type = sub_type;
00734            }
00735        }
00736        break;
00737 
00738       case POINTER :
00739        {
00740            ExtraData d;
00741            ExtraDataRec dr;
00742            XimFrameType sub_type;
00743 
00744            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00745               dr.fi = FrameInstInit(fi->template[fi->cur_no + 1].data);
00746               d = ChainMgrSetData(&fi->cm, fi->cur_no, dr);
00747            }
00748            sub_type = FrameInstGetNextType(d->fi, info);
00749            if (sub_type == EOL) {
00750               fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00751               ret_type = FrameInstGetNextType(fi, info);
00752            } else {
00753               ret_type = sub_type;
00754            }
00755        }
00756        break;
00757       default :
00758        /* Should never be reached */
00759        break;
00760     }
00761     return ret_type;
00762 }
00763 
00764 
00765 static XimFrameType FrameInstPeekNextType(FrameInst fi,
00766                                      XimFrameTypeInfo info)
00767 {
00768     XimFrameType ret_type;
00769 
00770     ret_type = fi->template[fi->cur_no].type;
00771 
00772     switch (ret_type) {
00773       case BIT8 :
00774       case BIT16 :
00775       case BIT32 :
00776       case EOL :
00777        break;
00778 
00779       case COUNTER_BIT8 :
00780       case COUNTER_BIT16 :
00781       case COUNTER_BIT32 :
00782        if (info) {
00783            register int offset, iter_idx;
00784 
00785            info->counter.is_byte_len = 
00786               ((int)fi->template[fi->cur_no].data & 0xff) == FmCounterByte;
00787            offset = (int)fi->template[fi->cur_no].data >> 8;
00788            iter_idx = fi->cur_no + offset;
00789            if (fi->template[iter_idx].type == ITER) {
00790               ExtraData d;
00791               ExtraDataRec dr;
00792 
00793               if ((d = ChainMgrGetExtraData(&fi->cm, iter_idx)) == NULL) {
00794                   dr.iter = IterInit(&fi->template[iter_idx + 1], NO_VALUE);
00795                   d = ChainMgrSetData(&fi->cm, iter_idx, dr);
00796               }
00797               info->counter.iter = d->iter;
00798            } else {
00799               /* Should not be reached here */
00800            }
00801        }
00802        break;
00803 
00804       case BARRAY :
00805        if (info) {
00806            ExtraData d;
00807 
00808            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00809               info->num = NO_VALUE;
00810            } else {
00811               info->num = d->num;
00812            }
00813        }
00814        break;
00815 
00816       case PADDING :
00817        if (info) {
00818            register int unit, number, size, i;
00819 
00820            unit = _UNIT(fi->template[fi->cur_no].data);
00821            number = _NUMBER(fi->template[fi->cur_no].data);
00822            
00823            i = fi->cur_no;
00824            size = 0;
00825            while (number > 0) {
00826                i = _FrameInstDecrement(fi->template, i);
00827               size += _FrameInstGetItemSize(fi, i);
00828               number--;
00829            }
00830            info->num = (unit - (size % unit)) % unit;
00831        }
00832        break;
00833        
00834       case ITER :
00835        {
00836            ExtraData d;
00837            ExtraDataRec dr;
00838            XimFrameType sub_type;
00839 
00840 
00841            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00842               dr.iter = IterInit(&fi->template[fi->cur_no + 1], NO_VALUE);
00843               d = ChainMgrSetData(&fi->cm, fi->cur_no, dr);
00844            }
00845            sub_type = IterPeekNextType(d->iter, info);
00846            if (sub_type == EOL) {
00847               ret_type = FrameInstPeekNextType(fi, info);
00848            } else {
00849               ret_type = sub_type;
00850            }
00851        }
00852        break;
00853 
00854       case POINTER :
00855        {
00856            ExtraData d;
00857            ExtraDataRec dr;
00858            XimFrameType sub_type;
00859 
00860            if ((d = ChainMgrGetExtraData(&fi->cm, fi->cur_no)) == NULL) {
00861               dr.fi = FrameInstInit(fi->template[fi->cur_no + 1].data);
00862               d = ChainMgrSetData(&fi->cm, fi->cur_no, dr);
00863            }
00864            sub_type = FrameInstPeekNextType(d->fi, info);
00865            if (sub_type == EOL) {
00866               ret_type = FrameInstPeekNextType(fi, info);
00867            } else {
00868               ret_type = sub_type;
00869            }
00870        }
00871        break;
00872       default :
00873        /* If comes here, bug! */
00874        break;
00875     }
00876     return ret_type;
00877 }
00878 
00879 
00880 static Bool FrameInstIsIterLoopEnd(FrameInst fi)
00881 {
00882     Bool ret = False;
00883 
00884     if (fi->template[fi->cur_no].type == ITER) {
00885        ExtraData d = ChainMgrGetExtraData(&fi->cm, fi->cur_no);
00886        Bool yourself;
00887 
00888        if (d) {
00889            ret = IterIsLoopEnd(d->iter, &yourself);
00890            if (ret && yourself) {
00891               fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
00892            }
00893        }
00894     }
00895 
00896     return(ret);
00897 }
00898 
00899 
00900 static FrameIter _FrameMgrAppendIter(FrameMgr fm, Iter it, int end)
00901 {
00902     FrameIter p = fm->iters;
00903 
00904     while (p && p->next) {
00905        p = p->next;
00906     }
00907     if (!p) {
00908        fm->iters = p = (FrameIter)Xmalloc(sizeof(FrameIterRec));
00909     }
00910     else {
00911        p->next = (FrameIter)Xmalloc(sizeof(FrameIterRec));
00912        p = p->next;
00913     }
00914     if (p) {
00915        p->iter = it;
00916        p->counting = False;
00917        p->counter = 0;
00918        p->end = end;
00919        p->next = NULL;
00920     }
00921 
00922     return(p);
00923 }
00924 
00925 
00926 static void _FrameMgrRemoveIter(FrameMgr fm, FrameIter it)
00927 {
00928     FrameIter prev, p;
00929 
00930     prev = NULL;
00931     p = fm->iters;
00932     while (p) {
00933        if (p == it) {
00934            if (prev) {
00935               prev->next = p->next;
00936            }
00937            else {
00938               fm->iters = p->next;
00939            }
00940            Xfree(p);
00941            break;
00942        }
00943        else {
00944            prev = p;
00945            p = p->next;
00946        }
00947     }
00948 }
00949 
00950 
00951 static FrameIter _FrameIterCounterIncr(FrameIter fitr, int i)
00952 {
00953     FrameIter p = fitr;
00954 
00955     while (p) {
00956        if (p->counting) {
00957            p->counter += i;
00958            if (p->counter >= p->end) {
00959               IterFixIteration(p->iter);
00960               return(p);
00961            }
00962        }
00963        p = p->next;
00964     }
00965     return(NULL);
00966 }
00967 
00968 
00969 static void _IterStartWatch(Iter it, void* client_data)
00970 {
00971     FrameIter p = (FrameIter)client_data;
00972     p->counting = True;
00973 }
00974 
00975 
00976 static FmStatus FrameInstSetSize(FrameInst fi, int num)
00977 {
00978     ExtraData d;
00979     ExtraDataRec dr;
00980     XimFrameType type;
00981     register int i;
00982 
00983     i = 0;
00984     while ((type = fi->template[i].type) != EOL) {
00985        if (type == BARRAY) {
00986            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
00987               dr.num = -1;
00988               d = ChainMgrSetData(&fi->cm, i, dr);
00989            }
00990            if (d->num == NO_VALUE) {
00991               d->num = num;
00992               return FmSuccess;
00993            }
00994        } else if (type == ITER) {
00995            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
00996               dr.iter = IterInit(&fi->template[i + 1], NO_VALUE);
00997               d = ChainMgrSetData(&fi->cm, i, dr);
00998            }
00999            if (IterSetSize(d->iter, num) == FmSuccess) {
01000               return FmSuccess;
01001            }
01002        } else if (type == POINTER) {
01003            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01004               dr.fi = FrameInstInit(fi->template[i + 1].data);
01005               d = ChainMgrSetData(&fi->cm, i, dr);
01006            }
01007            if (FrameInstSetSize(d->fi, num) == FmSuccess) {
01008               return FmSuccess;
01009            }
01010        }
01011        i = _FrameInstIncrement(fi->template, i);
01012     }
01013     return FmNoMoreData;
01014 }
01015 
01016 
01017 static int FrameInstGetSize(FrameInst fi)
01018 {
01019     XimFrameType type;
01020     register int i;
01021     ExtraData d;
01022     ExtraDataRec dr;
01023 
01024     i = fi->cur_no;
01025     while ((type = fi->template[i].type) != EOL) {
01026        if (type == BARRAY) {
01027            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01028               return NO_VALUE;
01029            }
01030            return d->num;
01031        } else if (type == ITER) {
01032            int ret_size;
01033            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01034               dr.iter = IterInit(&fi->template[i + 1], NO_VALUE);
01035               d = ChainMgrSetData(&fi->cm, i, dr);
01036            }
01037            ret_size = IterGetSize(d->iter);
01038            if (ret_size != NO_VALID_FIELD)
01039               return ret_size;
01040        } else if (type == POINTER) {
01041            int ret_size;
01042            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01043               dr.fi = FrameInstInit(fi->template[i + 1].data);
01044               d = ChainMgrSetData(&fi->cm, i, dr);
01045            }
01046            ret_size = FrameInstGetSize(d->fi);
01047            if (ret_size != NO_VALID_FIELD)
01048                return ret_size;
01049        }
01050        i = _FrameInstIncrement(fi->template, i);
01051     }
01052     return NO_VALID_FIELD;
01053 }
01054 
01055 
01056 static FmStatus FrameInstSetIterCount(FrameInst fi, int num)
01057 {
01058     ExtraData d;
01059     ExtraDataRec dr;
01060     register int i;
01061     XimFrameType type;
01062 
01063     i = 0;
01064     while ((type = fi->template[i].type) != EOL) {
01065        if (type == ITER) {
01066            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01067               dr.iter = IterInit(&fi->template[i + 1], num);
01068               (void)ChainMgrSetData(&fi->cm, i, dr);
01069               return FmSuccess;
01070            }
01071            if (IterSetIterCount(d->iter, num) == FmSuccess) {
01072               return FmSuccess;
01073            }
01074        } else if (type == POINTER) {
01075            if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL) {
01076               dr.fi = FrameInstInit(fi->template[i + 1].data);
01077               d = ChainMgrSetData(&fi->cm, i, dr);
01078            }
01079            if (FrameInstSetIterCount(d->fi, num) == FmSuccess) {
01080               return FmSuccess;
01081            }
01082        }
01083        i = _FrameInstIncrement(fi->template, i);
01084     }
01085     return FmNoMoreData;
01086 }
01087 
01088 
01089 static int FrameInstGetTotalSize(FrameInst fi)
01090 {
01091     register int size, i;
01092 
01093     size = 0;
01094 
01095     i = 0;
01096 
01097     while (fi->template[i].type != EOL) {
01098         size += _FrameInstGetItemSize(fi, i);
01099        i = _FrameInstIncrement(fi->template, i);
01100     }
01101     return size;
01102 }
01103 
01104 
01105 static void FrameInstReset(FrameInst fi)
01106 {
01107     ChainIterRec ci;
01108     int frame_no;
01109     ExtraDataRec d;
01110 
01111     ChainIterInit(&ci, &fi->cm);
01112 
01113     while (ChainIterGetNext(&ci, &frame_no, &d)) {
01114        register XimFrameType type;
01115        type = fi->template[frame_no].type;
01116        if (type == ITER) {
01117            if (d.iter)
01118               IterReset(d.iter);
01119        } else if (type == POINTER) {
01120            if (d.fi)
01121               FrameInstReset(d.fi);
01122        }
01123     }
01124     ChainIterFree(&ci);
01125 
01126     fi->cur_no = 0;
01127 }
01128 
01129 
01130 static Iter IterInit(XimFrame frame, int count)
01131 {
01132     Iter it;
01133     register XimFrameType type;
01134 
01135     it = (Iter)Xmalloc(sizeof(IterRec));
01136     it->template = frame;
01137     it->max_count = (count == NO_VALUE) ? 0 : count;
01138     it->allow_expansion = count == NO_VALUE;
01139     it->cur_no = 0;
01140     it->start_watch_proc = NULL;
01141     it->client_data = NULL;
01142     it->start_counter = False;
01143 
01144     type = frame->type;
01145     if (type & COUNTER_MASK) {  /* COUNTER_XXX cannot be an item of a ITER */
01146        Xfree(it);
01147        return NULL;
01148     }
01149 
01150     if (type == BIT8 || type == BIT16 || type == BIT32
01151        ) {
01152        /* Do nothing */;
01153     } else if (type == BARRAY || type == ITER || type == POINTER) {
01154        ChainMgrInit(&it->cm);
01155     } else {
01156        Xfree(it);
01157        return NULL;/* This should never occur */
01158     }
01159     return it;
01160 }
01161 
01162 
01163 static void IterFree(Iter it)
01164 {
01165     if (it->template->type == BARRAY) {
01166        ChainMgrFree(&it->cm);
01167     } else if (it->template->type == ITER) {
01168        ChainIterRec ci;
01169        int count;
01170        ExtraDataRec d;
01171 
01172        ChainIterInit(&ci, &it->cm);
01173        while (ChainIterGetNext(&ci, &count, &d)) {
01174            IterFree(d.iter);
01175        }
01176        ChainIterFree(&ci);
01177        ChainMgrFree(&it->cm);
01178     } else if (it->template->type == POINTER) {
01179        ChainIterRec ci;
01180        int count;
01181        ExtraDataRec dr;
01182 
01183        ChainIterInit(&ci, &it->cm);
01184        while (ChainIterGetNext(&ci, &count, &dr)) {
01185            FrameInstFree(dr.fi);
01186        }
01187        ChainIterFree(&ci);
01188        ChainMgrFree(&it->cm);
01189     }
01190     Xfree(it);
01191 }
01192 
01193 
01194 static Bool IterIsLoopEnd(Iter it, Bool* myself)
01195 {
01196     Bool ret = False;
01197     *myself = False;
01198 
01199     if (!it->allow_expansion && (it->cur_no == it->max_count)) {
01200        *myself = True;
01201        ret = True;
01202     }
01203     else if (it->template->type == POINTER) {
01204        ExtraData d = ChainMgrGetExtraData(&it->cm, it->cur_no);
01205        if (d) {
01206            if (FrameInstIsIterLoopEnd(d->fi)) {
01207               ret = True;
01208            }
01209            else {
01210               if (FrameInstIsEnd(d->fi)) {
01211                   it->cur_no++;
01212                   if (!it->allow_expansion && (it->cur_no == it->max_count)) {
01213                      *myself = True;
01214                      ret = True;
01215                   }
01216               }
01217            }
01218        }
01219     }
01220     else if (it->template->type == ITER) {
01221        ExtraData d = ChainMgrGetExtraData(&it->cm, it->cur_no);
01222        if (d) {
01223            Bool yourself;
01224            if (IterIsLoopEnd(d->iter, &yourself)) {
01225               ret = True;
01226            }
01227        }
01228     }
01229 
01230     return(ret);
01231 }
01232 
01233 
01234 static XimFrameType IterGetNextType(Iter it, XimFrameTypeInfo info)
01235 {
01236     XimFrameType type = it->template->type;
01237 
01238     if (it->start_counter) {
01239        (*it->start_watch_proc)(it, it->client_data);
01240        it->start_counter = False;
01241     }
01242 
01243     if (it->cur_no >= it->max_count) {
01244        if (it->allow_expansion) {
01245            it->max_count = it->cur_no + 1;
01246        } else {
01247            return EOL;
01248        }
01249     }
01250 
01251     if (type == BIT8 || type == BIT16 || type == BIT32
01252        ) {
01253        it->cur_no++;
01254        return type;
01255     } else if (type == BARRAY) {
01256        ExtraData d;
01257 
01258        if (info) {
01259            if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01260               info->num = NO_VALUE;
01261            } else {
01262               info->num = d->num;
01263            }
01264        }
01265        it->cur_no++;
01266        return BARRAY;
01267     } else if (type == ITER) {
01268        XimFrameType ret_type;
01269        ExtraData d;
01270        ExtraDataRec dr;
01271 
01272        if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01273            dr.iter = IterInit(it->template + 1, NO_VALUE);
01274            d = ChainMgrSetData(&it->cm, it->cur_no, dr);
01275        }
01276 
01277        ret_type = IterGetNextType(d->iter, info);
01278        if (ret_type == EOL) {
01279            it->cur_no++;
01280            ret_type = IterGetNextType(it, info);
01281        }
01282        return ret_type;
01283     } else if (type == POINTER) {
01284        XimFrameType ret_type;
01285        ExtraData d;
01286        ExtraDataRec dr;
01287 
01288        if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01289            dr.fi = FrameInstInit(it->template[1].data);
01290            d = ChainMgrSetData(&it->cm, it->cur_no, dr);
01291        }
01292        
01293        ret_type = FrameInstGetNextType(d->fi, info);
01294        if (ret_type == EOL) {
01295            it->cur_no++;
01296            ret_type = IterGetNextType(it, info);
01297        }
01298        return ret_type;
01299     } else {
01300        ;/* This should never occur */
01301     }
01302     return EOL;
01303 }
01304 
01305 
01306 static XimFrameType IterPeekNextType(Iter it, XimFrameTypeInfo info)
01307 {
01308     XimFrameType type = it->template->type;
01309 
01310     if (!it->allow_expansion && (it->cur_no >= it->max_count)) {
01311        return(EOL);
01312     }
01313 
01314     if (type == BIT8 || type == BIT16 || type == BIT32) {
01315        return(type);
01316     }
01317     else if (type == BARRAY) {
01318        ExtraData d;
01319 
01320        if (info) {
01321            if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01322               info->num = NO_VALUE;
01323            } else {
01324               info->num = d->num;
01325            }
01326        }
01327        return(BARRAY);
01328     }
01329     else if (type == ITER) {
01330        XimFrameType ret_type;
01331        ExtraData d;
01332        ExtraDataRec dr;
01333 
01334        if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01335            dr.iter = IterInit(it->template + 1, NO_VALUE);
01336            d = ChainMgrSetData(&it->cm, it->cur_no, dr);
01337        }
01338 
01339        ret_type = IterPeekNextType(d->iter, info);
01340        if (ret_type == EOL) {
01341            ret_type = IterPeekNextType(it, info);
01342        }
01343        return(ret_type);
01344     }
01345     else if (type == POINTER) {
01346        XimFrameType ret_type;
01347        ExtraData d;
01348        ExtraDataRec dr;
01349 
01350        if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01351            dr.fi = FrameInstInit(it->template[1].data);
01352            d = ChainMgrSetData(&it->cm, it->cur_no, dr);
01353        }
01354        
01355        ret_type = FrameInstPeekNextType(d->fi, info);
01356        if (ret_type == EOL) {
01357            ret_type = IterPeekNextType(it, info);
01358        }
01359        return(ret_type);
01360     }
01361     else {
01362        ;/* If comes here, bug! */
01363     }
01364     return EOL;
01365 }
01366 
01367 
01368 static FmStatus IterSetSize(Iter it, int num)
01369 {
01370     XimFrameType type;
01371     register int i;
01372 
01373     if (!it->allow_expansion && it->max_count == 0) {
01374        return FmNoMoreData;
01375     }
01376 
01377     type = it->template->type;
01378     if (type == BARRAY) {
01379        ExtraData d;
01380        ExtraDataRec dr;
01381        for (i = 0; i < it->max_count; i++) {
01382            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01383               dr.num = NO_VALUE;
01384               d = ChainMgrSetData(&it->cm, i, dr);
01385            }
01386            if (d->num == NO_VALUE) {
01387               d->num = num;
01388               return FmSuccess;
01389            }
01390        }
01391        if (it->allow_expansion) {
01392            ExtraDataRec dr;
01393            dr.num = num;
01394            (void)ChainMgrSetData(&it->cm, it->max_count, dr);
01395            it->max_count++;
01396 
01397            return FmSuccess;
01398        }
01399        return FmNoMoreData;
01400     } else if (type == ITER) {
01401        ExtraData d;
01402        ExtraDataRec dr;
01403        for (i = 0; i < it->max_count; i++) {
01404            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01405               dr.iter = IterInit(it->template + 1, NO_VALUE);
01406               d = ChainMgrSetData(&it->cm, i, dr);
01407            }
01408            if (IterSetSize(d->iter, num) == FmSuccess) {
01409               return FmSuccess;
01410            }
01411        }
01412        if (it->allow_expansion) {
01413            ExtraDataRec dr;
01414            dr.iter = IterInit(it->template + 1, NO_VALUE);
01415            (void)ChainMgrSetData(&it->cm, it->max_count, dr);
01416            it->max_count++;
01417 
01418            if (IterSetSize(dr.iter, num) == FmSuccess) {
01419               return FmSuccess;
01420            }
01421        }
01422        return FmNoMoreData;
01423     } else if (type == POINTER) {
01424        ExtraData d;
01425        ExtraDataRec dr;
01426        for (i = 0; i < it->max_count; i++) {
01427            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01428               dr.fi = FrameInstInit(it->template[1].data);
01429               d = ChainMgrSetData(&it->cm, i, dr);
01430            }
01431            if (FrameInstSetSize(d->fi, num) == FmSuccess) {
01432               return FmSuccess;
01433            }
01434        }
01435        if (it->allow_expansion) {
01436            ExtraDataRec dr;
01437            dr.fi = FrameInstInit(it->template[1].data);
01438            (void)ChainMgrSetData(&it->cm, it->max_count, dr);
01439            it->max_count++;
01440 
01441            if (FrameInstSetSize(dr.fi, num) == FmSuccess) {
01442               return FmSuccess;
01443            }
01444        }
01445        return FmNoMoreData;
01446     }
01447     return FmNoMoreData;
01448 }
01449 
01450 
01451 static int IterGetSize(Iter it)
01452 {
01453     register int i;
01454     ExtraData d;
01455     ExtraDataRec dr;
01456 
01457     if (it->cur_no >= it->max_count) {
01458        return NO_VALID_FIELD;
01459     }
01460 
01461     if (it->template->type == BARRAY) {
01462        if ((d = ChainMgrGetExtraData(&it->cm, it->cur_no)) == NULL) {
01463            return NO_VALUE;
01464        }
01465        return d->num;
01466     } else if (it->template->type == ITER) {
01467        for (i = it->cur_no; i < it->max_count; i++) {
01468            int ret_size;
01469            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01470               dr.iter = IterInit(it->template + 1, NO_VALUE);
01471               d = ChainMgrSetData(&it->cm, i, dr);
01472            }
01473            ret_size = IterGetSize(d->iter);
01474            if (ret_size == NO_VALID_FIELD)
01475               continue;
01476            else
01477               return ret_size;
01478        }
01479        return NO_VALID_FIELD;
01480     } else if (it->template->type == POINTER) {
01481        for (i = it->cur_no; i < it->max_count; i++) {
01482            int ret_size;
01483            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01484               dr.fi = FrameInstInit(it->template[1].data);
01485               d = ChainMgrSetData(&it->cm, i, dr);
01486            }
01487            ret_size = FrameInstGetSize(d->fi);
01488            if (ret_size == NO_VALID_FIELD)
01489               continue;
01490            else
01491               return ret_size;
01492        }
01493        return NO_VALID_FIELD;
01494     }
01495     return NO_VALID_FIELD;
01496 }
01497 
01498 
01499 static FmStatus IterSetIterCount(Iter it, int num)
01500 {
01501     register int i;
01502 
01503     if (it->allow_expansion) {
01504        it->max_count = num;
01505        it->allow_expansion = False;
01506        return FmSuccess;
01507     }
01508 
01509     if (it->max_count == 0) {
01510        return FmNoMoreData;
01511     }
01512 
01513     if (it->template->type == ITER) {
01514        for (i = 0; i < it->max_count; i++) {
01515            ExtraData d;
01516            ExtraDataRec dr;
01517            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01518               dr.iter = IterInit(it->template + 1, num);
01519               (void)ChainMgrSetData(&it->cm, i, dr);
01520               return FmSuccess;
01521            }
01522            if (IterSetIterCount(d->iter, num) == FmSuccess)
01523               return FmSuccess;
01524        }
01525        if (it->allow_expansion) {
01526            ExtraDataRec dr;
01527            dr.iter = IterInit(it->template + 1, num);
01528            (void)ChainMgrSetData(&it->cm, it->max_count, dr);
01529            it->max_count++;
01530            
01531            return FmSuccess;
01532        }
01533     } else if (it->template->type == POINTER) {
01534        for (i = 0; i < it->max_count; i++) {
01535            ExtraData d;
01536            ExtraDataRec dr;
01537            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01538               dr.fi = FrameInstInit(it->template[1].data);
01539               d = ChainMgrSetData(&it->cm, i, dr);
01540            }
01541            if (FrameInstSetIterCount(d->fi, num) == FmSuccess)
01542               return FmSuccess;
01543        }
01544        if (it->allow_expansion) {
01545            ExtraDataRec dr;
01546            dr.fi = FrameInstInit(it->template[1].data);
01547            (void)ChainMgrSetData(&it->cm, it->max_count, dr);
01548            it->max_count++;
01549 
01550            if (FrameInstSetIterCount(dr.fi, num) == FmSuccess)
01551               return FmSuccess;
01552        }
01553     }
01554     return FmNoMoreData;
01555 }
01556 
01557 
01558 static int IterGetTotalSize(Iter it)
01559 {
01560     register int size, i;
01561     XimFrameType type;
01562 
01563     if (it->allow_expansion)
01564        return NO_VALUE;
01565     else if (it->max_count == 0)
01566        return 0;
01567 
01568     type = it->template->type;
01569 
01570     size = 0;
01571 
01572     if (type == BIT8)
01573        size = it->max_count;
01574     else if (type == BIT16)
01575        size = it->max_count * 2;
01576     else if (type == BIT32)
01577        size = it->max_count * 4;
01578     else if (type == BARRAY) {
01579        for (i = 0; i < it->max_count; i++) {
01580            register int num;
01581            ExtraData d;
01582            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01583               return NO_VALUE;
01584            }
01585            if ((num = d->num) == NO_VALUE)
01586               return NO_VALUE;
01587            size += num;
01588        }
01589     } else if (type == ITER) {
01590        for (i = 0; i < it->max_count; i++) {
01591            register int num;
01592            ExtraData d;
01593            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01594               return NO_VALUE;
01595            }
01596            if ((num = IterGetTotalSize(d->iter)) == NO_VALUE)
01597               return NO_VALUE;
01598            size += num;
01599        }
01600     } else if (type == POINTER) {
01601        for (i = 0; i < it->max_count; i++) {
01602            register int num;
01603            ExtraData d;
01604            ExtraDataRec dr;
01605            if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL) {
01606               dr.fi = FrameInstInit(it->template[1].data);
01607               d = ChainMgrSetData(&it->cm, i, dr);
01608            }
01609            if ((num = FrameInstGetTotalSize(d->fi)) == NO_VALUE)
01610               return NO_VALUE;
01611            size += num;
01612        }
01613     } else {
01614        ;/* Should never reached */
01615     }
01616     return size;
01617 }
01618 
01619 
01620 static void IterReset(Iter it)
01621 {
01622     if (it->template->type == ITER) {
01623        ChainIterRec ci;
01624        int count;
01625        ExtraDataRec d;
01626 
01627        ChainIterInit(&ci, &it->cm);
01628        while (ChainIterGetNext(&ci, &count, &d)) {
01629            IterReset(d.iter);
01630        }
01631        ChainIterFree(&ci);
01632     } else if (it->template->type == POINTER) {
01633        ChainIterRec ci;
01634        int count;
01635        ExtraDataRec dr;
01636 
01637        ChainIterInit(&ci, &it->cm);
01638        while (ChainIterGetNext(&ci, &count, &dr)) {
01639            FrameInstReset(dr.fi);
01640        }
01641        ChainIterFree(&ci);
01642     }
01643     it->cur_no = 0;
01644 }
01645 
01646 
01647 static void IterSetStartWatch(Iter it, 
01648                            IterStartWatchProc proc, void* client_data)
01649 {
01650     it->start_watch_proc = proc;
01651     it->client_data = client_data;
01652 }
01653 
01654 
01655 static ExtraData ChainMgrSetData(ChainMgr cm, int frame_no, ExtraDataRec data)
01656 {
01657     Chain cur = (Chain)Xmalloc(sizeof(ChainRec));
01658 
01659     cur->frame_no = frame_no;
01660     cur->d = data;
01661     cur->next = NULL;
01662 
01663     if (cm->top == NULL) {
01664        cm->top = cm->tail = cur;
01665     } else {
01666        cm->tail->next = cur;
01667        cm->tail = cur;
01668     }
01669     return &cur->d;
01670 }
01671 
01672 
01673 static ExtraData ChainMgrGetExtraData(ChainMgr cm, int frame_no)
01674 {
01675     Chain cur;
01676 
01677     cur = cm->top;
01678 
01679     while (cur) {
01680        if (cur->frame_no == frame_no) {
01681            return &cur->d;
01682        }
01683        cur = cur->next;
01684     }
01685     return NULL;
01686 }
01687 
01688 
01689 static Bool ChainIterGetNext(ChainIter ci, int* frame_no, ExtraData d)
01690 {
01691     if (ci->cur == NULL)
01692        return False;
01693 
01694     *frame_no = ci->cur->frame_no;
01695     *d = ci->cur->d;
01696 
01697     ci->cur = ci->cur->next;
01698 
01699     return True;
01700 }
01701 
01702 
01703 static int _FrameInstIncrement(XimFrame frame, int count)
01704 {
01705     XimFrameType type;
01706 
01707     type = frame[count].type;
01708     type &= ~COUNTER_MASK;
01709     
01710     switch (type) {
01711       case BIT8:
01712       case BIT16:
01713       case BIT32:
01714 #if 0 /* Temporary hack - 64 bit support */
01715       case BIT64:
01716 #endif
01717       case BARRAY:
01718       case PADDING:
01719        return count + 1;
01720         break;
01721       case POINTER:
01722        return count + 2;
01723        break;
01724       case ITER:
01725        return _FrameInstIncrement(frame, count + 1);
01726        break;
01727       default:
01728        break;
01729     }
01730     return -1;   /* Error */
01731 }
01732 
01733 
01734 static int _FrameInstDecrement(XimFrame frame, int count)
01735 {
01736     register int i;
01737     XimFrameType type;
01738 
01739     if (count == 0)
01740        return -1;   /* cannot decrement */
01741     else if (count == 1) {
01742        return 0;    /* BOGUS - It should check the contents of data */
01743     }
01744 
01745     type = frame[count - 2].type;
01746     type &= ~COUNTER_MASK;
01747 
01748     switch (type) {
01749       case BIT8:
01750       case BIT16:
01751       case BIT32:
01752       case BARRAY:
01753       case PADDING:
01754       case PTR_ITEM:
01755        return count - 1;
01756        break;
01757       case POINTER:
01758       case ITER:
01759        i = count - 3;
01760        while (i >= 0) {
01761            if (frame[i].type != ITER)
01762                return i + 1;
01763            i--;
01764        }
01765        return 0;
01766       default:
01767        break;
01768     }
01769     return -1;   /* Error */
01770 }
01771 
01772 
01773 static int _FrameInstGetItemSize(FrameInst fi, int cur_no)
01774 {
01775     XimFrameType type;
01776 
01777     type = fi->template[cur_no].type;
01778     type &= ~COUNTER_MASK;
01779 
01780     switch (type) {
01781       case BIT8 :
01782        return 1;
01783        break;
01784 
01785       case BIT16 :
01786         return 2;
01787        break;
01788 
01789       case BIT32 :
01790        return 4;
01791        break;
01792 
01793       case BARRAY :
01794        {
01795          ExtraData d;
01796          
01797          if ((d = ChainMgrGetExtraData(&fi->cm, cur_no)) == NULL)
01798              return NO_VALUE;
01799          if (d->num == NO_VALUE)
01800              return NO_VALUE;
01801          return d->num;
01802        }
01803        break;
01804 
01805       case PADDING :
01806        {
01807          register int unit, number, size, i;
01808 
01809          unit = _UNIT(fi->template[cur_no].data);
01810          number = _NUMBER(fi->template[cur_no].data);
01811 
01812          i = cur_no;
01813          size = 0;
01814          while (number > 0) {
01815              i = _FrameInstDecrement(fi->template, i);
01816              size += _FrameInstGetItemSize(fi, i);
01817              number--;
01818          }
01819          size = (unit - (size % unit)) % unit;
01820          return size;
01821        }
01822        break;
01823 
01824       case ITER :
01825        {
01826          ExtraData d;
01827          int sub_size;
01828          
01829          if ((d = ChainMgrGetExtraData(&fi->cm, cur_no)) == NULL)
01830              return NO_VALUE;
01831          sub_size = IterGetTotalSize(d->iter);
01832          if (sub_size == NO_VALUE)
01833              return NO_VALUE;
01834          return sub_size;
01835        }
01836        break;
01837 
01838       case POINTER :
01839        {
01840          ExtraData d;
01841          int sub_size;
01842 
01843          if ((d = ChainMgrGetExtraData(&fi->cm, cur_no)) == NULL)
01844              return NO_VALUE;
01845          sub_size = FrameInstGetTotalSize(d->fi);
01846          if (sub_size == NO_VALUE)
01847              return NO_VALUE;
01848          return sub_size;
01849        }
01850        break;
01851       default :
01852        break;
01853     }
01854     return NO_VALUE;
01855 }