OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [exp_simple.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclUnixNotify.c --
3
 *
4
 *      This file contains Unix-specific procedures for the notifier,
5
 *      which is the lowest-level part of the Tcl event loop.  This file
6
 *      works together with ../generic/tclNotify.c.
7
 *
8
 * Copyright (c) 1995 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 */
13
 
14
static char sccsid[] = "@(#) tclUnixNotify.c 1.27 96/01/19 10:30:23";
15
 
16
#include "tclInt.h"
17
#include "tclPort.h"
18
#include <signal.h> 
19
 
20
/*
21
 * The information below is used to provide read, write, and
22
 * exception masks to select during calls to Tcl_DoOneEvent.
23
 */
24
 
25
static fd_mask checkMasks[3*MASK_SIZE];
26
                                /* This array is used to build up the masks
27
                                 * to be used in the next call to select.
28
                                 * Bits are set in response to calls to
29
                                 * Tcl_WatchFile. */
30
static fd_mask readyMasks[3*MASK_SIZE];
31
                                /* This array reflects the readable/writable
32
                                 * conditions that were found to exist by the
33
                                 * last call to select. */
34
static int numFdBits;           /* Number of valid bits in checkMasks
35
                                 * (one more than highest fd for which
36
                                 * Tcl_WatchFile has been called). */
37
 
38
/*
39
 *----------------------------------------------------------------------
40
 *
41
 * Tcl_WatchFile --
42
 *
43
 *      Arrange for Tcl_DoOneEvent to include this file in the masks
44
 *      for the next call to select.  This procedure is invoked by
45
 *      event sources, which are in turn invoked by Tcl_DoOneEvent
46
 *      before it invokes select.
47
 *
48
 * Results:
49
 *      None.
50
 *
51
 * Side effects:
52
 *
53
 *      The notifier will generate a file event when the I/O channel
54
 *      given by fd next becomes ready in the way indicated by mask.
55
 *      If fd is already registered then the old mask will be replaced
56
 *      with the new one.  Once the event is sent, the notifier will
57
 *      not send any more events about the fd until the next call to
58
 *      Tcl_NotifyFile.
59
 *
60
 *----------------------------------------------------------------------
61
 */
62
 
63
void
64
Tcl_WatchFile(file, mask)
65
    Tcl_File file;      /* Generic file handle for a stream. */
66
    int mask;                   /* OR'ed combination of TCL_READABLE,
67
                                 * TCL_WRITABLE, and TCL_EXCEPTION:
68
                                 * indicates conditions to wait for
69
                                 * in select. */
70
{
71
    int fd, type, index;
72
    fd_mask bit;
73
 
74
    fd = (int) Tcl_GetFileInfo(file, &type);
75
 
76
    if (type != TCL_UNIX_FD) {
77
        panic("Tcl_WatchFile: unexpected file type");
78
    }
79
 
80
    if (fd >= FD_SETSIZE) {
81
        panic("Tcl_WatchFile can't handle file id %d", fd);
82
    }
83
 
84
    index = fd/(NBBY*sizeof(fd_mask));
85
    bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
86
    if (mask & TCL_READABLE) {
87
        checkMasks[index] |= bit;
88
    }
89
    if (mask & TCL_WRITABLE) {
90
        (checkMasks+MASK_SIZE)[index] |= bit;
91
    }
92
    if (mask & TCL_EXCEPTION) {
93
        (checkMasks+2*(MASK_SIZE))[index] |= bit;
94
    }
95
    if (numFdBits <= fd) {
96
        numFdBits = fd+1;
97
    }
98
}
99
 
100
/*
101
 *----------------------------------------------------------------------
102
 *
103
 * Tcl_FileReady --
104
 *
105
 *      Indicates what conditions (readable, writable, etc.) were
106
 *      present on a file the last time the notifier invoked select.
107
 *      This procedure is typically invoked by event sources to see
108
 *      if they should queue events.
109
 *
110
 * Results:
111
 *      The return value is 0 if none of the conditions specified by mask
112
 *      was true for fd the last time the system checked.  If any of the
113
 *      conditions were true, then the return value is a mask of those
114
 *      that were true.
115
 *
116
 * Side effects:
117
 *      None.
118
 *
119
 *----------------------------------------------------------------------
120
 */
121
 
122
int
123
Tcl_FileReady(file, mask)
124
    Tcl_File file;      /* Generic file handle for a stream. */
125
    int mask;                   /* OR'ed combination of TCL_READABLE,
126
                                 * TCL_WRITABLE, and TCL_EXCEPTION:
127
                                 * indicates conditions caller cares about. */
128
{
129
    int index, result, type, fd;
130
    fd_mask bit;
131
 
132
    fd = (int) Tcl_GetFileInfo(file, &type);
133
    if (type != TCL_UNIX_FD) {
134
        panic("Tcl_FileReady: unexpected file type");
135
    }
136
 
137
    index = fd/(NBBY*sizeof(fd_mask));
138
    bit = 1 << (fd%(NBBY*sizeof(fd_mask)));
139
    result = 0;
140
    if ((mask & TCL_READABLE) && (readyMasks[index] & bit)) {
141
        result |= TCL_READABLE;
142
    }
143
    if ((mask & TCL_WRITABLE) && ((readyMasks+MASK_SIZE)[index] & bit)) {
144
        result |= TCL_WRITABLE;
145
    }
146
    if ((mask & TCL_EXCEPTION) && ((readyMasks+(2*MASK_SIZE))[index] & bit)) {
147
        result |= TCL_EXCEPTION;
148
    }
149
    return result;
150
}
151
 
152
/*
153
 *----------------------------------------------------------------------
154
 *
155
 * Tcl_WaitForEvent --
156
 *
157
 *      This procedure does the lowest level wait for events in a
158
 *      platform-specific manner.  It uses information provided by
159
 *      previous calls to Tcl_WatchFile, plus the timePtr argument,
160
 *      to determine what to wait for and how long to wait.
161
 *
162
 * Results:
163
 *      None.
164
 *
165
 * Side effects:
166
 *      May put the process to sleep for a while, depending on timePtr.
167
 *      When this procedure returns, an event of interest to the application
168
 *      has probably, but not necessarily, occurred.
169
 *
170
 *----------------------------------------------------------------------
171
 */
172
 
173
void
174
Tcl_WaitForEvent(timePtr)
175
    Tcl_Time *timePtr;          /* Specifies the maximum amount of time
176
                                 * that this procedure should block before
177
                                 * returning.  The time is given as an
178
                                 * interval, not an absolute wakeup time.
179
                                 * NULL means block forever. */
180
{
181
    struct timeval timeout, *timeoutPtr;
182
    int numFound;
183
 
184
    memcpy((VOID *) readyMasks, (VOID *) checkMasks,
185
            3*MASK_SIZE*sizeof(fd_mask));
186
    if (timePtr == NULL) {
187
        timeoutPtr = NULL;
188
    } else {
189
        timeoutPtr = &timeout;
190
        timeout.tv_sec = timePtr->sec;
191
        timeout.tv_usec = timePtr->usec;
192
    }
193
    numFound = select(numFdBits, (SELECT_MASK *) &readyMasks[0],
194
            (SELECT_MASK *) &readyMasks[MASK_SIZE],
195
            (SELECT_MASK *) &readyMasks[2*MASK_SIZE], timeoutPtr);
196
 
197
    /*
198
     * Some systems don't clear the masks after an error, so
199
     * we have to do it here.
200
     */
201
 
202
    if (numFound == -1) {
203
        memset((VOID *) readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask));
204
    }
205
 
206
    /*
207
     * Reset the check masks in preparation for the next call to
208
     * select.
209
     */
210
 
211
    numFdBits = 0;
212
    memset((VOID *) checkMasks, 0, 3*MASK_SIZE*sizeof(fd_mask));
213
}
214
 
215
/*
216
 *----------------------------------------------------------------------
217
 *
218
 * Tcl_Sleep --
219
 *
220
 *      Delay execution for the specified number of milliseconds.
221
 *
222
 * Results:
223
 *      None.
224
 *
225
 * Side effects:
226
 *      Time passes.
227
 *
228
 *----------------------------------------------------------------------
229
 */
230
 
231
void
232
Tcl_Sleep(ms)
233
    int ms;                     /* Number of milliseconds to sleep. */
234
{
235
    static struct timeval delay;
236
    Tcl_Time before, after;
237
 
238
    /*
239
     * The only trick here is that select appears to return early
240
     * under some conditions, so we have to check to make sure that
241
     * the right amount of time really has elapsed.  If it's too
242
     * early, go back to sleep again.
243
     */
244
 
245
    TclGetTime(&before);
246
    after = before;
247
    after.sec += ms/1000;
248
    after.usec += (ms%1000)*1000;
249
    if (after.usec > 1000000) {
250
        after.usec -= 1000000;
251
        after.sec += 1;
252
    }
253
    while (1) {
254
        delay.tv_sec = after.sec - before.sec;
255
        delay.tv_usec = after.usec - before.usec;
256
        if (delay.tv_usec < 0) {
257
            delay.tv_usec += 1000000;
258
            delay.tv_sec -= 1;
259
        }
260
 
261
        /*
262
         * Special note:  must convert delay.tv_sec to int before comparing
263
         * to zero, since delay.tv_usec is unsigned on some platforms.
264
         */
265
 
266
        if ((((int) delay.tv_sec) < 0)
267
                || ((delay.tv_usec == 0) && (delay.tv_sec == 0))) {
268
            break;
269
        }
270
        (void) select(0, (SELECT_MASK *) 0, (SELECT_MASK *) 0,
271
                (SELECT_MASK *) 0, &delay);
272
        TclGetTime(&before);
273
    }
274
}
275
 
276
 
277
 
278
 
279
 
280
 
281
 
282
#if 0 /* WHOLE FILE */
283
 
284
 
285
 
286
/* interact (with only one process) - give user keyboard control
287
 
288
Written by: Don Libes, NIST, 2/6/90
289
 
290
Design and implementation of this program was paid for by U.S. tax
291
dollars.  Therefore it is public domain.  However, the author and NIST
292
would appreciate credit if this program or parts of it are used.
293
*/
294
 
295
/* This file exists for deficient versions of UNIX that lack select,
296
poll, or some other multiplexing hook.  Instead, this code uses two
297
processes per spawned process.  One sends characters from the spawnee
298
to the spawner; a second send chars the other way.
299
 
300
This will work on any UNIX system.  The only sacrifice is that it
301
doesn't support multiple processes.  Eventually, it should catch
302
SIGCHLD on dead processes and do the right thing.  But it is pretty
303
gruesome to imagine so many processes to do all this.  If you change
304
it successfully, please mail back the changes to me.  - Don
305
*/
306
 
307
#include "expect_cf.h"
308
#include <stdio.h>
309
#include <sys/types.h>
310
#include <sys/time.h>
311
 
312
#ifdef HAVE_SYS_WAIT_H
313
#include <sys/wait.h>
314
#endif
315
 
316
#include "tcl.h"
317
#include "exp_prog.h"
318
#include "exp_command.h"        /* for struct exp_f defs */
319
#include "exp_event.h"
320
 
321
/*ARGSUSED*/
322
void
323
exp_arm_background_filehandler(m)
324
int m;
325
{
326
}
327
 
328
/*ARGSUSED*/
329
void
330
exp_disarm_background_filehandler(m)
331
int m;
332
{
333
}
334
 
335
/*ARGSUSED*/
336
void
337
exp_disarm_background_filehandler_force(m)
338
int m;
339
{
340
}
341
 
342
/*ARGSUSED*/
343
void
344
exp_unblock_background_filehandler(m)
345
int m;
346
{
347
}
348
 
349
/*ARGSUSED*/
350
void
351
exp_block_background_filehandler(m)
352
int m;
353
{
354
}
355
 
356
/*ARGSUSED*/
357
void
358
exp_event_disarm(fd)
359
int fd;
360
{
361
}
362
 
363
/* returns status, one of EOF, TIMEOUT, ERROR or DATA */
364
/*ARGSUSED*/
365
int
366
exp_get_next_event(interp,masters, n,master_out,timeout,key)
367
Tcl_Interp *interp;
368
int *masters;
369
int n;                  /* # of masters */
370
int *master_out;        /* 1st event master, not set if none */
371
int timeout;            /* seconds */
372
int key;
373
{
374
        int m;
375
        struct exp_f *f;
376
 
377
        if (n > 1) {
378
                exp_error(interp,"expect not compiled with multiprocess support");
379
                /* select a different INTERACT_TYPE in Makefile */
380
                return(TCL_ERROR);
381
        }
382
 
383
        m = *master_out = masters[0];
384
        f = exp_fs + m;
385
 
386
        if (f->key != key) {
387
                f->key = key;
388
                f->force_read = FALSE;
389
                return(EXP_DATA_OLD);
390
        } else if ((!f->force_read) && (f->size != 0)) {
391
                return(EXP_DATA_OLD);
392
        }
393
 
394
        return(EXP_DATA_NEW);
395
}
396
 
397
/*ARGSUSED*/
398
int
399
exp_get_next_event_info(interp,fd,ready_mask)
400
Tcl_Interp *interp;
401
int fd;
402
int ready_mask;
403
{
404
}
405
 
406
/* There is no portable way to do sub-second sleeps on such a system, so */
407
/* do the next best thing (without a busy loop) and fake it: sleep the right */
408
/* amount of time over the long run.  Note that while "subtotal" isn't */
409
/* reinitialized, it really doesn't matter for such a gross hack as random */
410
/* scheduling pauses will easily introduce occasional one second delays. */
411
int     /* returns TCL_XXX */
412
exp_dsleep(interp,sec)
413
Tcl_Interp *interp;
414
double sec;
415
{
416
        static double subtotal = 0;
417
        int seconds;
418
 
419
        subtotal += sec;
420
        if (subtotal < 1) return TCL_OK;
421
        seconds = subtotal;
422
        subtotal -= seconds;
423
 restart:
424
        if (Tcl_AsyncReady()) {
425
                int rc = Tcl_AsyncInvoke(interp,TCL_OK);
426
                if (rc != TCL_OK) return(rc);
427
        }
428
        sleep(seconds);
429
        return TCL_OK;
430
}
431
 
432
#if 0
433
/* There is no portable way to do sub-second sleeps on such a system, so */
434
/* do the next best thing (without a busy loop) and fake it: sleep the right */
435
/* amount of time over the long run.  Note that while "subtotal" isn't */
436
/* reinitialized, it really doesn't matter for such a gross hack as random */
437
/* scheduling pauses will easily introduce occasional one second delays. */
438
int     /* returns TCL_XXX */
439
exp_usleep(interp,usec)
440
Tcl_Interp *interp;
441
long usec;              /* microseconds */
442
{
443
        static subtotal = 0;
444
        int seconds;
445
 
446
        subtotal += usec;
447
        if (subtotal < 1000000) return TCL_OK;
448
        seconds = subtotal/1000000;
449
        subtotal = subtotal%1000000;
450
 restart:
451
        if (Tcl_AsyncReady()) {
452
                int rc = Tcl_AsyncInvoke(interp,TCL_OK);
453
                if (rc != TCL_OK) return(exp_tcl2_returnvalue(rc));
454
        }
455
        sleep(seconds);
456
        return TCL_OK;
457
}
458
#endif /*0*/
459
 
460
/* set things up for later calls to event handler */
461
void
462
exp_init_event()
463
{
464
        exp_event_exit = 0;
465
}
466
 
467
#endif /* WHOLE FILE! */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.