os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclIO.h
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* 
sl@0
     2
 * tclIO.h --
sl@0
     3
 *
sl@0
     4
 *	This file provides the generic portions (those that are the same on
sl@0
     5
 *	all platforms and for all channel types) of Tcl's IO facilities.
sl@0
     6
 *
sl@0
     7
 * Copyright (c) 1998-2000 Ajuba Solutions
sl@0
     8
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
sl@0
     9
 *
sl@0
    10
 * See the file "license.terms" for information on usage and redistribution
sl@0
    11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    12
 *
sl@0
    13
 * RCS: @(#) $Id: tclIO.h,v 1.5.4.2 2004/07/15 20:46:19 andreas_kupries Exp $
sl@0
    14
 */
sl@0
    15
sl@0
    16
/*
sl@0
    17
 * Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not
sl@0
    18
 * compile on systems where neither is defined. We want both defined so
sl@0
    19
 * that we can test safely for both. In the code we still have to test for
sl@0
    20
 * both because there may be systems on which both are defined and have
sl@0
    21
 * different values.
sl@0
    22
 */
sl@0
    23
sl@0
    24
#if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN)))
sl@0
    25
#   define EWOULDBLOCK EAGAIN
sl@0
    26
#endif
sl@0
    27
#if ((!defined(EAGAIN)) && (defined(EWOULDBLOCK)))
sl@0
    28
#   define EAGAIN EWOULDBLOCK
sl@0
    29
#endif
sl@0
    30
#if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK)))
sl@0
    31
error one of EWOULDBLOCK or EAGAIN must be defined
sl@0
    32
#endif
sl@0
    33
sl@0
    34
/*
sl@0
    35
 * The following structure encapsulates the state for a background channel
sl@0
    36
 * copy.  Note that the data buffer for the copy will be appended to this
sl@0
    37
 * structure.
sl@0
    38
 */
sl@0
    39
sl@0
    40
typedef struct CopyState {
sl@0
    41
    struct Channel *readPtr;	/* Pointer to input channel. */
sl@0
    42
    struct Channel *writePtr;	/* Pointer to output channel. */
sl@0
    43
    int readFlags;		/* Original read channel flags. */
sl@0
    44
    int writeFlags;		/* Original write channel flags. */
sl@0
    45
    int toRead;			/* Number of bytes to copy, or -1. */
sl@0
    46
    int total;			/* Total bytes transferred (written). */
sl@0
    47
    Tcl_Interp *interp;		/* Interp that started the copy. */
sl@0
    48
    Tcl_Obj *cmdPtr;		/* Command to be invoked at completion. */
sl@0
    49
    int bufSize;		/* Size of appended buffer. */
sl@0
    50
    char buffer[1];		/* Copy buffer, this must be the last
sl@0
    51
				 * field. */
sl@0
    52
} CopyState;
sl@0
    53
sl@0
    54
/*
sl@0
    55
 * struct ChannelBuffer:
sl@0
    56
 *
sl@0
    57
 * Buffers data being sent to or from a channel.
sl@0
    58
 */
sl@0
    59
sl@0
    60
typedef struct ChannelBuffer {
sl@0
    61
    int nextAdded;		/* The next position into which a character
sl@0
    62
                                 * will be put in the buffer. */
sl@0
    63
    int nextRemoved;		/* Position of next byte to be removed
sl@0
    64
                                 * from the buffer. */
sl@0
    65
    int bufLength;		/* How big is the buffer? */
sl@0
    66
    struct ChannelBuffer *nextPtr;
sl@0
    67
    				/* Next buffer in chain. */
sl@0
    68
    char buf[4];		/* Placeholder for real buffer. The real
sl@0
    69
                                 * buffer occuppies this space + bufSize-4
sl@0
    70
                                 * bytes. This must be the last field in
sl@0
    71
                                 * the structure. */
sl@0
    72
} ChannelBuffer;
sl@0
    73
sl@0
    74
#define CHANNELBUFFER_HEADER_SIZE	(sizeof(ChannelBuffer) - 4)
sl@0
    75
sl@0
    76
/*
sl@0
    77
 * How much extra space to allocate in buffer to hold bytes from previous
sl@0
    78
 * buffer (when converting to UTF-8) or to hold bytes that will go to
sl@0
    79
 * next buffer (when converting from UTF-8).
sl@0
    80
 */
sl@0
    81
 
sl@0
    82
#define BUFFER_PADDING	    16
sl@0
    83
 
sl@0
    84
/*
sl@0
    85
 * The following defines the *default* buffer size for channels.
sl@0
    86
 */
sl@0
    87
sl@0
    88
#define CHANNELBUFFER_DEFAULT_SIZE	(1024 * 4)
sl@0
    89
sl@0
    90
/*
sl@0
    91
 * Structure to record a close callback. One such record exists for
sl@0
    92
 * each close callback registered for a channel.
sl@0
    93
 */
sl@0
    94
sl@0
    95
typedef struct CloseCallback {
sl@0
    96
    Tcl_CloseProc *proc;		/* The procedure to call. */
sl@0
    97
    ClientData clientData;		/* Arbitrary one-word data to pass
sl@0
    98
					 * to the callback. */
sl@0
    99
    struct CloseCallback *nextPtr;	/* For chaining close callbacks. */
sl@0
   100
} CloseCallback;
sl@0
   101
sl@0
   102
/*
sl@0
   103
 * The following structure describes the information saved from a call to
sl@0
   104
 * "fileevent". This is used later when the event being waited for to
sl@0
   105
 * invoke the saved script in the interpreter designed in this record.
sl@0
   106
 */
sl@0
   107
sl@0
   108
typedef struct EventScriptRecord {
sl@0
   109
    struct Channel *chanPtr;	/* The channel for which this script is
sl@0
   110
				 * registered. This is used only when an
sl@0
   111
				 * error occurs during evaluation of the
sl@0
   112
				 * script, to delete the handler. */
sl@0
   113
    Tcl_Obj *scriptPtr;		/* Script to invoke. */
sl@0
   114
    Tcl_Interp *interp;		/* In what interpreter to invoke script? */
sl@0
   115
    int mask;			/* Events must overlap current mask for the
sl@0
   116
				 * stored script to be invoked. */
sl@0
   117
    struct EventScriptRecord *nextPtr;
sl@0
   118
				/* Next in chain of records. */
sl@0
   119
} EventScriptRecord;
sl@0
   120
sl@0
   121
/*
sl@0
   122
 * struct Channel:
sl@0
   123
 *
sl@0
   124
 * One of these structures is allocated for each open channel. It contains data
sl@0
   125
 * specific to the channel but which belongs to the generic part of the Tcl
sl@0
   126
 * channel mechanism, and it points at an instance specific (and type
sl@0
   127
 * specific) * instance data, and at a channel type structure.
sl@0
   128
 */
sl@0
   129
sl@0
   130
typedef struct Channel {
sl@0
   131
    struct ChannelState *state; /* Split out state information */
sl@0
   132
sl@0
   133
    ClientData instanceData;	/* Instance-specific data provided by
sl@0
   134
				 * creator of channel. */
sl@0
   135
    Tcl_ChannelType *typePtr;	/* Pointer to channel type structure. */
sl@0
   136
sl@0
   137
    struct Channel *downChanPtr;/* Refers to channel this one was stacked
sl@0
   138
				 * upon.  This reference is NULL for normal
sl@0
   139
				 * channels.  See Tcl_StackChannel. */
sl@0
   140
    struct Channel *upChanPtr;	/* Refers to the channel above stacked this
sl@0
   141
				 * one. NULL for the top most channel. */
sl@0
   142
sl@0
   143
    /*
sl@0
   144
     * Intermediate buffers to hold pre-read data for consumption by a
sl@0
   145
     * newly stacked transformation. See 'Tcl_StackChannel'.
sl@0
   146
     */
sl@0
   147
    ChannelBuffer *inQueueHead;	/* Points at first buffer in input queue. */
sl@0
   148
    ChannelBuffer *inQueueTail;	/* Points at last buffer in input queue. */
sl@0
   149
} Channel;
sl@0
   150
sl@0
   151
/*
sl@0
   152
 * struct ChannelState:
sl@0
   153
 *
sl@0
   154
 * One of these structures is allocated for each open channel. It contains data
sl@0
   155
 * specific to the channel but which belongs to the generic part of the Tcl
sl@0
   156
 * channel mechanism, and it points at an instance specific (and type
sl@0
   157
 * specific) * instance data, and at a channel type structure.
sl@0
   158
 */
sl@0
   159
sl@0
   160
typedef struct ChannelState {
sl@0
   161
    CONST char *channelName;	/* The name of the channel instance in Tcl
sl@0
   162
				 * commands. Storage is owned by the generic IO
sl@0
   163
				 * code, is dynamically allocated. */
sl@0
   164
    int	flags;			/* ORed combination of the flags defined
sl@0
   165
				 * below. */
sl@0
   166
    Tcl_Encoding encoding;	/* Encoding to apply when reading or writing
sl@0
   167
				 * data on this channel.  NULL means no
sl@0
   168
				 * encoding is applied to data. */
sl@0
   169
    Tcl_EncodingState inputEncodingState;
sl@0
   170
				/* Current encoding state, used when converting
sl@0
   171
				 * input data bytes to UTF-8. */
sl@0
   172
    int inputEncodingFlags;	/* Encoding flags to pass to conversion
sl@0
   173
				 * routine when converting input data bytes to
sl@0
   174
				 * UTF-8.  May be TCL_ENCODING_START before
sl@0
   175
				 * converting first byte and TCL_ENCODING_END
sl@0
   176
				 * when EOF is seen. */
sl@0
   177
    Tcl_EncodingState outputEncodingState;
sl@0
   178
				/* Current encoding state, used when converting
sl@0
   179
				 * UTF-8 to output data bytes. */
sl@0
   180
    int outputEncodingFlags;	/* Encoding flags to pass to conversion
sl@0
   181
				 * routine when converting UTF-8 to output
sl@0
   182
				 * data bytes.  May be TCL_ENCODING_START
sl@0
   183
				 * before converting first byte and
sl@0
   184
				 * TCL_ENCODING_END when EOF is seen. */
sl@0
   185
    TclEolTranslation inputTranslation;
sl@0
   186
				/* What translation to apply for end of line
sl@0
   187
				 * sequences on input? */    
sl@0
   188
    TclEolTranslation outputTranslation;
sl@0
   189
				/* What translation to use for generating
sl@0
   190
				 * end of line sequences in output? */
sl@0
   191
    int inEofChar;		/* If nonzero, use this as a signal of EOF
sl@0
   192
				 * on input. */
sl@0
   193
    int outEofChar;             /* If nonzero, append this to the channel
sl@0
   194
				 * when it is closed if it is open for
sl@0
   195
				 * writing. */
sl@0
   196
    int unreportedError;	/* Non-zero if an error report was deferred
sl@0
   197
				 * because it happened in the background. The
sl@0
   198
				 * value is the POSIX error code. */
sl@0
   199
    int refCount;		/* How many interpreters hold references to
sl@0
   200
				 * this IO channel? */
sl@0
   201
sl@0
   202
    CloseCallback *closeCbPtr;	/* Callbacks registered to be called when the
sl@0
   203
				 * channel is closed. */
sl@0
   204
    char *outputStage;		/* Temporary staging buffer used when
sl@0
   205
				 * translating EOL before converting from
sl@0
   206
				 * UTF-8 to external form. */
sl@0
   207
    ChannelBuffer *curOutPtr;	/* Current output buffer being filled. */
sl@0
   208
    ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */
sl@0
   209
    ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */
sl@0
   210
sl@0
   211
    ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates
sl@0
   212
				 * need to allocate a new buffer for "gets"
sl@0
   213
				 * that crosses buffer boundaries. */
sl@0
   214
    ChannelBuffer *inQueueHead;	/* Points at first buffer in input queue. */
sl@0
   215
    ChannelBuffer *inQueueTail;	/* Points at last buffer in input queue. */
sl@0
   216
sl@0
   217
    struct ChannelHandler *chPtr;/* List of channel handlers registered
sl@0
   218
				  * for this channel. */
sl@0
   219
    int interestMask;		/* Mask of all events this channel has
sl@0
   220
				 * handlers for. */
sl@0
   221
    EventScriptRecord *scriptRecordPtr;
sl@0
   222
				/* Chain of all scripts registered for
sl@0
   223
				 * event handlers ("fileevent") on this
sl@0
   224
				 * channel. */
sl@0
   225
sl@0
   226
    int bufSize;		/* What size buffers to allocate? */
sl@0
   227
    Tcl_TimerToken timer;	/* Handle to wakeup timer for this channel. */
sl@0
   228
    CopyState *csPtr;		/* State of background copy, or NULL. */
sl@0
   229
    Channel *topChanPtr;	/* Refers to topmost channel in a stack.
sl@0
   230
				 * Never NULL. */
sl@0
   231
    Channel *bottomChanPtr;	/* Refers to bottommost channel in a stack.
sl@0
   232
				 * This channel can be relied on to live as
sl@0
   233
				 * long as the channel state. Never NULL. */
sl@0
   234
    struct ChannelState *nextCSPtr;
sl@0
   235
				/* Next in list of channels currently open. */
sl@0
   236
    Tcl_ThreadId managingThread; /* TIP #10: Id of the thread managing
sl@0
   237
				  * this stack of channels. */
sl@0
   238
} ChannelState;
sl@0
   239
    
sl@0
   240
/*
sl@0
   241
 * Values for the flags field in Channel. Any ORed combination of the
sl@0
   242
 * following flags can be stored in the field. These flags record various
sl@0
   243
 * options and state bits about the channel. In addition to the flags below,
sl@0
   244
 * the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set.
sl@0
   245
 */
sl@0
   246
sl@0
   247
#define CHANNEL_NONBLOCKING	(1<<3)	/* Channel is currently in
sl@0
   248
					 * nonblocking mode. */
sl@0
   249
#define CHANNEL_LINEBUFFERED	(1<<4)	/* Output to the channel must be
sl@0
   250
					 * flushed after every newline. */
sl@0
   251
#define CHANNEL_UNBUFFERED	(1<<5)	/* Output to the channel must always
sl@0
   252
					 * be flushed immediately. */
sl@0
   253
#define BUFFER_READY		(1<<6)	/* Current output buffer (the
sl@0
   254
					 * curOutPtr field in the
sl@0
   255
                                         * channel structure) should be
sl@0
   256
                                         * output as soon as possible even
sl@0
   257
                                         * though it may not be full. */
sl@0
   258
#define BG_FLUSH_SCHEDULED	(1<<7)	/* A background flush of the
sl@0
   259
					 * queued output buffers has been
sl@0
   260
                                         * scheduled. */
sl@0
   261
#define CHANNEL_CLOSED		(1<<8)	/* Channel has been closed. No
sl@0
   262
					 * further Tcl-level IO on the
sl@0
   263
                                         * channel is allowed. */
sl@0
   264
#define CHANNEL_EOF		(1<<9)	/* EOF occurred on this channel.
sl@0
   265
					 * This bit is cleared before every
sl@0
   266
                                         * input operation. */
sl@0
   267
#define CHANNEL_STICKY_EOF	(1<<10)	/* EOF occurred on this channel because
sl@0
   268
					 * we saw the input eofChar. This bit
sl@0
   269
                                         * prevents clearing of the EOF bit
sl@0
   270
                                         * before every input operation. */
sl@0
   271
#define CHANNEL_BLOCKED		(1<<11)	/* EWOULDBLOCK or EAGAIN occurred
sl@0
   272
					 * on this channel. This bit is
sl@0
   273
					 * cleared before every input or
sl@0
   274
					 * output operation. */
sl@0
   275
#define INPUT_SAW_CR		(1<<12)	/* Channel is in CRLF eol input
sl@0
   276
					 * translation mode and the last
sl@0
   277
                                         * byte seen was a "\r". */
sl@0
   278
#define INPUT_NEED_NL		(1<<15)	/* Saw a '\r' at end of last buffer,
sl@0
   279
					 * and there should be a '\n' at
sl@0
   280
					 * beginning of next buffer. */
sl@0
   281
#define CHANNEL_DEAD		(1<<13)	/* The channel has been closed by
sl@0
   282
					 * the exit handler (on exit) but
sl@0
   283
                                         * not deallocated. When any IO
sl@0
   284
                                         * operation sees this flag on a
sl@0
   285
                                         * channel, it does not call driver
sl@0
   286
                                         * level functions to avoid referring
sl@0
   287
                                         * to deallocated data. */
sl@0
   288
#define CHANNEL_NEED_MORE_DATA	(1<<14)	/* The last input operation failed
sl@0
   289
					 * because there was not enough data
sl@0
   290
					 * to complete the operation.  This
sl@0
   291
					 * flag is set when gets fails to
sl@0
   292
					 * get a complete line or when read
sl@0
   293
					 * fails to get a complete character.
sl@0
   294
					 * When set, file events will not be
sl@0
   295
					 * delivered for buffered data until
sl@0
   296
					 * the state of the channel changes. */
sl@0
   297
#define CHANNEL_RAW_MODE	(1<<16)	/* When set, notes that the Raw API is
sl@0
   298
					 * being used. */
sl@0
   299
#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING
sl@0
   300
#define CHANNEL_TIMER_FEV       (1<<17) /* When set the event we are
sl@0
   301
					 * notified by is a fileevent
sl@0
   302
					 * generated by a timer. We
sl@0
   303
					 * don't know if the driver
sl@0
   304
					 * has more data and should
sl@0
   305
					 * not try to read from it. If
sl@0
   306
					 * the system needs more than
sl@0
   307
					 * is in the buffers out read
sl@0
   308
					 * routines will simulate a
sl@0
   309
					 * short read (0 characters
sl@0
   310
					 * read) */
sl@0
   311
#define CHANNEL_HAS_MORE_DATA   (1<<18) /* Set by NotifyChannel for a
sl@0
   312
					 * channel if and only if the
sl@0
   313
					 * channel is configured
sl@0
   314
					 * non-blocking, the driver
sl@0
   315
					 * for said channel has no
sl@0
   316
					 * blockmodeproc, and data has
sl@0
   317
					 * arrived for reading at the
sl@0
   318
					 * OS level). A GetInput will
sl@0
   319
					 * pass reading from the
sl@0
   320
					 * driver if the channel is
sl@0
   321
					 * non-blocking, without
sl@0
   322
					 * blockmode proc and the flag
sl@0
   323
					 * has not been set. A read
sl@0
   324
					 * will be performed if the
sl@0
   325
					 * flag is set. This will
sl@0
   326
					 * reset the flag as well. */
sl@0
   327
#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */
sl@0
   328
sl@0
   329
#define CHANNEL_INCLOSE		(1<<19)	/* Channel is currently being
sl@0
   330
					 * closed. Its structures are
sl@0
   331
					 * still live and usable, but
sl@0
   332
					 * it may not be closed again
sl@0
   333
					 * from within the close handler.
sl@0
   334
					 */
sl@0
   335
sl@0
   336
/*
sl@0
   337
 * For each channel handler registered in a call to Tcl_CreateChannelHandler,
sl@0
   338
 * there is one record of the following type. All of records for a specific
sl@0
   339
 * channel are chained together in a singly linked list which is stored in
sl@0
   340
 * the channel structure.
sl@0
   341
 */
sl@0
   342
sl@0
   343
typedef struct ChannelHandler {
sl@0
   344
    Channel *chanPtr;		/* The channel structure for this channel. */
sl@0
   345
    int mask;			/* Mask of desired events. */
sl@0
   346
    Tcl_ChannelProc *proc;	/* Procedure to call in the type of
sl@0
   347
                                 * Tcl_CreateChannelHandler. */
sl@0
   348
    ClientData clientData;	/* Argument to pass to procedure. */
sl@0
   349
    struct ChannelHandler *nextPtr;
sl@0
   350
    				/* Next one in list of registered handlers. */
sl@0
   351
} ChannelHandler;
sl@0
   352
sl@0
   353
/*
sl@0
   354
 * This structure keeps track of the current ChannelHandler being invoked in
sl@0
   355
 * the current invocation of ChannelHandlerEventProc. There is a potential
sl@0
   356
 * problem if a ChannelHandler is deleted while it is the current one, since
sl@0
   357
 * ChannelHandlerEventProc needs to look at the nextPtr field. To handle this
sl@0
   358
 * problem, structures of the type below indicate the next handler to be
sl@0
   359
 * processed for any (recursively nested) dispatches in progress. The
sl@0
   360
 * nextHandlerPtr field is updated if the handler being pointed to is deleted.
sl@0
   361
 * The nextPtr field is used to chain together all recursive invocations, so
sl@0
   362
 * that Tcl_DeleteChannelHandler can find all the recursively nested
sl@0
   363
 * invocations of ChannelHandlerEventProc and compare the handler being
sl@0
   364
 * deleted against the NEXT handler to be invoked in that invocation; when it
sl@0
   365
 * finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr
sl@0
   366
 * field of the structure to the next handler.
sl@0
   367
 */
sl@0
   368
sl@0
   369
typedef struct NextChannelHandler {
sl@0
   370
    ChannelHandler *nextHandlerPtr;	/* The next handler to be invoked in
sl@0
   371
                                         * this invocation. */
sl@0
   372
    struct NextChannelHandler *nestedHandlerPtr;
sl@0
   373
    /* Next nested invocation of
sl@0
   374
     * ChannelHandlerEventProc. */
sl@0
   375
} NextChannelHandler;
sl@0
   376
sl@0
   377
sl@0
   378
/*
sl@0
   379
 * The following structure describes the event that is added to the Tcl
sl@0
   380
 * event queue by the channel handler check procedure.
sl@0
   381
 */
sl@0
   382
sl@0
   383
typedef struct ChannelHandlerEvent {
sl@0
   384
    Tcl_Event header;		/* Standard header for all events. */
sl@0
   385
    Channel *chanPtr;		/* The channel that is ready. */
sl@0
   386
    int readyMask;		/* Events that have occurred. */
sl@0
   387
} ChannelHandlerEvent;
sl@0
   388
sl@0
   389
/*
sl@0
   390
 * The following structure is used by Tcl_GetsObj() to encapsulates the
sl@0
   391
 * state for a "gets" operation.
sl@0
   392
 */
sl@0
   393
 
sl@0
   394
typedef struct GetsState {
sl@0
   395
    Tcl_Obj *objPtr;		/* The object to which UTF-8 characters
sl@0
   396
				 * will be appended. */
sl@0
   397
    char **dstPtr;		/* Pointer into objPtr's string rep where
sl@0
   398
				 * next character should be stored. */
sl@0
   399
    Tcl_Encoding encoding;	/* The encoding to use to convert raw bytes
sl@0
   400
				 * to UTF-8.  */
sl@0
   401
    ChannelBuffer *bufPtr;	/* The current buffer of raw bytes being
sl@0
   402
				 * emptied. */
sl@0
   403
    Tcl_EncodingState state;	/* The encoding state just before the last
sl@0
   404
				 * external to UTF-8 conversion in
sl@0
   405
				 * FilterInputBytes(). */
sl@0
   406
    int rawRead;		/* The number of bytes removed from bufPtr
sl@0
   407
				 * in the last call to FilterInputBytes(). */
sl@0
   408
    int bytesWrote;		/* The number of bytes of UTF-8 data
sl@0
   409
				 * appended to objPtr during the last call to
sl@0
   410
				 * FilterInputBytes(). */
sl@0
   411
    int charsWrote;		/* The corresponding number of UTF-8
sl@0
   412
				 * characters appended to objPtr during the
sl@0
   413
				 * last call to FilterInputBytes(). */
sl@0
   414
    int totalChars;		/* The total number of UTF-8 characters
sl@0
   415
				 * appended to objPtr so far, just before the
sl@0
   416
				 * last call to FilterInputBytes(). */
sl@0
   417
} GetsState;