1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
48
49
50
51
52
53
54
55
61
62
66
67
68
69
72
73
74
75
76
77
78
86
87
88
89
98
99
100
101
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
181
182
186
187
191
192
197
198
203
204
205
206
207
208
213
214
215
216
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
244
245
246
247
248
249
250
251
252
255
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
289
293
297
298
299
300
301
302
303
304
305
306
310
311
312
313
327
328
339
340
356
357
363
364
365
366
367
368
369
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
418
419
423
424
428
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
475
476
477
478
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
505
506
510
511
512
513
514
515
518
519
520
521
522
526
527
528
529
530
531
532
533
537
538
539
540
541
542
548
549
550
551
552
553
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
578
579
580
587
588
589
590
591
592
593
594
595
596
600
601
602
605
611
612
613
614
628
629
630
631
634
635
636
637
638
639
640
641
642
645
646
647
648
649
652
656
657
658
659
661
662
663
664
665
671
672
678
679
680
681
682
683
684
685
688
689
690
691
692
696
702
707
708
709
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
734
735
736
737
738
748
749
752
753
754
755
756
757
758
759
760
761
762
767
768
769
784
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
/* ... */
#include "jimautoconf.h"
#include <jim.h>
#include <jim-eventloop.h>
#include <time.h>
#include <string.h>
#include <errno.h>
6 includes#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#if defined(__MINGW32__)
#include <windows.h>
#include <winsock.h>
#ifndef HAVE_USLEEP
#define usleep(US) Sleep((US) / 1000)
#define HAVE_USLEEP
/* ... */#endif/* ... */
#else
#include <sys/types.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif/* ... */
#endif
#ifndef HAVE_USLEEP
#define usleep(US) sleep((US) / 1000000)
#warning "sub-second sleep not supported"/* ... */
#endif
typedef struct Jim_FileEvent
{
int fd;
int mask;
Jim_FileProc *fileProc;
Jim_EventFinalizerProc *finalizerProc;
void *clientData;
struct Jim_FileEvent *next;
...} Jim_FileEvent;
typedef struct Jim_TimeEvent
{
jim_wide id;
jim_wide initialus;
jim_wide when;
Jim_TimeProc *timeProc;
Jim_EventFinalizerProc *finalizerProc;
void *clientData;
struct Jim_TimeEvent *next;
...} Jim_TimeEvent;
typedef struct Jim_EventLoop
{
Jim_FileEvent *fileEventHead;
Jim_TimeEvent *timeEventHead;
jim_wide timeEventNextId;
time_t timeBase;
int suppress_bgerror;
...} Jim_EventLoop;
static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData);
static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData);
int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr)
{
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
Jim_CallFrame *savedFramePtr;
int retval;
savedFramePtr = interp->framePtr;
interp->framePtr = interp->topFramePtr;
retval = Jim_EvalObj(interp, scriptObjPtr);
interp->framePtr = savedFramePtr;
if (retval != JIM_OK && retval != JIM_RETURN && !eventLoop->suppress_bgerror) {
Jim_Obj *objv[2];
int rc = JIM_ERR;
objv[0] = Jim_NewStringObj(interp, "bgerror", -1);
objv[1] = Jim_GetResult(interp);
Jim_IncrRefCount(objv[0]);
Jim_IncrRefCount(objv[1]);
if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || (rc = Jim_EvalObjVector(interp, 2, objv)) != JIM_OK) {
if (rc == JIM_BREAK) {
eventLoop->suppress_bgerror++;
}if (rc == JIM_BREAK) { ... }
else {
Jim_MakeErrorMessage(interp);
fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
Jim_SetResultString(interp, "", -1);
}else { ... }
}if (Jim_GetCommand(interp, objv[0], JIM_NONE) == NULL || (rc = Jim_EvalObjVector(interp, 2, objv)) != JIM_OK) { ... }
Jim_DecrRefCount(interp, objv[0]);
Jim_DecrRefCount(interp, objv[1]);
}if (retval != JIM_OK && retval != JIM_RETURN && !eventLoop->suppress_bgerror) { ... }
return retval;
}{ ... }
/* ... */
void Jim_CreateFileHandler(Jim_Interp *interp, int fd, int mask,
Jim_FileProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
Jim_FileEvent *fe;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
fe = Jim_Alloc(sizeof(*fe));
fe->fd = fd;
fe->mask = mask;
fe->fileProc = proc;
fe->finalizerProc = finalizerProc;
fe->clientData = clientData;
fe->next = eventLoop->fileEventHead;
eventLoop->fileEventHead = fe;
}{ ... }
static int JimEventHandlerScript(Jim_Interp *interp, void *clientData, int mask)
{
return Jim_EvalObjBackground(interp, (Jim_Obj *)clientData);
}{ ... }
static void JimEventHandlerScriptFinalize(Jim_Interp *interp, void *clientData)
{
Jim_DecrRefCount(interp, (Jim_Obj *)clientData);
}{ ... }
/* ... */
void Jim_CreateScriptFileHandler(Jim_Interp *interp, int fd, int mask,
Jim_Obj *scriptObj)
{
Jim_IncrRefCount(scriptObj);
Jim_CreateFileHandler(interp, fd, mask, JimEventHandlerScript, scriptObj, JimEventHandlerScriptFinalize);
}{ ... }
/* ... */
void *Jim_FindFileHandler(Jim_Interp *interp, int fd, int mask)
{
Jim_FileEvent *fe;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
for (fe = eventLoop->fileEventHead; fe; fe = fe->next) {
if (fe->fd == fd && (fe->mask & mask)) {
return fe->clientData;
}if (fe->fd == fd && (fe->mask & mask)) { ... }
}for (fe = eventLoop->fileEventHead; fe; fe = fe->next) { ... }
return NULL;
}{ ... }
/* ... */
void Jim_DeleteFileHandler(Jim_Interp *interp, int fd, int mask)
{
Jim_FileEvent *fe, *next, *prev = NULL;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
for (fe = eventLoop->fileEventHead; fe; fe = next) {
next = fe->next;
if (fe->fd == fd && (fe->mask & mask)) {
if (prev == NULL)
eventLoop->fileEventHead = next;
else
prev->next = next;
if (fe->finalizerProc)
fe->finalizerProc(interp, fe->clientData);
Jim_Free(fe);
continue;
}if (fe->fd == fd && (fe->mask & mask)) { ... }
prev = fe;
}for (fe = eventLoop->fileEventHead; fe; fe = next) { ... }
}{ ... }
/* ... */
static jim_wide JimGetTimeUsec(Jim_EventLoop *eventLoop)
{
long long now;
struct timeval tv;
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC_RAW)
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) {
now = ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
}if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0) { ... }
else
#endif
{
gettimeofday(&tv, NULL);
now = tv.tv_sec * 1000000LL + tv.tv_usec;
}else { ... }
return now - eventLoop->timeBase;
}{ ... }
jim_wide Jim_CreateTimeHandler(Jim_Interp *interp, jim_wide us,
Jim_TimeProc * proc, void *clientData, Jim_EventFinalizerProc * finalizerProc)
{
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
jim_wide id = ++eventLoop->timeEventNextId;
Jim_TimeEvent *te, *e, *prev;
te = Jim_Alloc(sizeof(*te));
te->id = id;
te->initialus = us;
te->when = JimGetTimeUsec(eventLoop) + us;
te->timeProc = proc;
te->finalizerProc = finalizerProc;
te->clientData = clientData;
prev = NULL;
for (e = eventLoop->timeEventHead; e; e = e->next) {
if (te->when < e->when) {
break;
}if (te->when < e->when) { ... }
prev = e;
}for (e = eventLoop->timeEventHead; e; e = e->next) { ... }
if (prev) {
te->next = prev->next;
prev->next = te;
}if (prev) { ... }
else {
te->next = eventLoop->timeEventHead;
eventLoop->timeEventHead = te;
}else { ... }
return id;
}{ ... }
static jim_wide JimParseAfterId(Jim_Obj *idObj)
{
const char *tok = Jim_String(idObj);
jim_wide id;
if (strncmp(tok, "after#", 6) == 0 && Jim_StringToWide(tok + 6, &id, 10) == JIM_OK) {
return id;
}if (strncmp(tok, "after#", 6) == 0 && Jim_StringToWide(tok + 6, &id, 10) == JIM_OK) { ... }
return -1;
}{ ... }
static jim_wide JimFindAfterByScript(Jim_EventLoop *eventLoop, Jim_Obj *scriptObj)
{
Jim_TimeEvent *te;
for (te = eventLoop->timeEventHead; te; te = te->next) {
if (te->timeProc == JimAfterTimeHandler) {
if (Jim_StringEqObj(scriptObj, te->clientData)) {
return te->id;
}if (Jim_StringEqObj(scriptObj, te->clientData)) { ... }
}if (te->timeProc == JimAfterTimeHandler) { ... }
}for (te = eventLoop->timeEventHead; te; te = te->next) { ... }
return -1;
}{ ... }
static Jim_TimeEvent *JimFindTimeHandlerById(Jim_EventLoop *eventLoop, jim_wide id)
{
Jim_TimeEvent *te;
for (te = eventLoop->timeEventHead; te; te = te->next) {
if (te->id == id) {
return te;
}if (te->id == id) { ... }
}for (te = eventLoop->timeEventHead; te; te = te->next) { ... }
return NULL;
}{ ... }
static Jim_TimeEvent *Jim_RemoveTimeHandler(Jim_EventLoop *eventLoop, jim_wide id)
{
Jim_TimeEvent *te, *prev = NULL;
for (te = eventLoop->timeEventHead; te; te = te->next) {
if (te->id == id) {
if (prev == NULL)
eventLoop->timeEventHead = te->next;
else
prev->next = te->next;
return te;
}if (te->id == id) { ... }
prev = te;
}for (te = eventLoop->timeEventHead; te; te = te->next) { ... }
return NULL;
}{ ... }
static void Jim_FreeTimeHandler(Jim_Interp *interp, Jim_TimeEvent *te)
{
if (te->finalizerProc)
te->finalizerProc(interp, te->clientData);
Jim_Free(te);
}{ ... }
jim_wide Jim_DeleteTimeHandler(Jim_Interp *interp, jim_wide id)
{
Jim_TimeEvent *te;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
if (id > eventLoop->timeEventNextId) {
return -2;
}if (id > eventLoop->timeEventNextId) { ... }
te = Jim_RemoveTimeHandler(eventLoop, id);
if (te) {
jim_wide remain;
remain = te->when - JimGetTimeUsec(eventLoop);
remain = (remain < 0) ? 0 : remain;
Jim_FreeTimeHandler(interp, te);
return remain;
}if (te) { ... }
return -1;
}{ ... }
/* ... */
int Jim_ProcessEvents(Jim_Interp *interp, int flags)
{
jim_wide sleep_us = -1;
int processed = 0;
Jim_EventLoop *eventLoop = Jim_GetAssocData(interp, "eventloop");
Jim_FileEvent *fe = eventLoop->fileEventHead;
Jim_TimeEvent *te;
jim_wide maxId;
if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) {
if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) {
return -1;
}if ((flags & JIM_TIME_EVENTS) == 0 || eventLoop->timeEventHead == NULL) { ... }
}if ((flags & JIM_FILE_EVENTS) == 0 || fe == NULL) { ... }
/* ... */
if (flags & JIM_DONT_WAIT) {
sleep_us = 0;
}if (flags & JIM_DONT_WAIT) { ... }
else if (flags & JIM_TIME_EVENTS) {
if (eventLoop->timeEventHead) {
Jim_TimeEvent *shortest = eventLoop->timeEventHead;
/* ... */
sleep_us = shortest->when - JimGetTimeUsec(eventLoop);
if (sleep_us < 0) {
sleep_us = 0;
}if (sleep_us < 0) { ... }
}if (eventLoop->timeEventHead) { ... }
else {
sleep_us = -1;
}else { ... }
}else if (flags & JIM_TIME_EVENTS) { ... }
#ifdef HAVE_SELECT
if (flags & JIM_FILE_EVENTS) {
int retval;
struct timeval tv, *tvp = NULL;
fd_set rfds, wfds, efds;
int maxfd = -1;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
while (fe != NULL) {
if (fe->mask & JIM_EVENT_READABLE)
FD_SET(fe->fd, &rfds);
if (fe->mask & JIM_EVENT_WRITABLE)
FD_SET(fe->fd, &wfds);
if (fe->mask & JIM_EVENT_EXCEPTION)
FD_SET(fe->fd, &efds);
if (maxfd < fe->fd)
maxfd = fe->fd;
fe = fe->next;
}while (fe != NULL) { ... }
if (sleep_us >= 0) {
tvp = &tv;
tvp->tv_sec = sleep_us / 1000000;
tvp->tv_usec = sleep_us % 1000000;
}if (sleep_us >= 0) { ... }
retval = select(maxfd + 1, &rfds, &wfds, &efds, tvp);
if (retval < 0) {
if (errno == EINVAL) {
Jim_SetResultString(interp, "non-waitable filehandle", -1);
return -2;
}if (errno == EINVAL) { ... }
}if (retval < 0) { ... }
else if (retval > 0) {
fe = eventLoop->fileEventHead;
while (fe != NULL) {
int mask = 0;
int fd = fe->fd;
if ((fe->mask & JIM_EVENT_READABLE) && FD_ISSET(fd, &rfds))
mask |= JIM_EVENT_READABLE;
if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds))
mask |= JIM_EVENT_WRITABLE;
if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds))
mask |= JIM_EVENT_EXCEPTION;
if (mask) {
int ret = fe->fileProc(interp, fe->clientData, mask);
if (ret != JIM_OK && ret != JIM_RETURN) {
Jim_DeleteFileHandler(interp, fd, mask);
}if (ret != JIM_OK && ret != JIM_RETURN) { ... }
processed++;
/* ... */
FD_CLR(fd, &rfds);
FD_CLR(fd, &wfds);
FD_CLR(fd, &efds);
fe = eventLoop->fileEventHead;
}if (mask) { ... }
else {
fe = fe->next;
}else { ... }
}while (fe != NULL) { ... }
}else if (retval > 0) { ... }
}if (flags & JIM_FILE_EVENTS) { ... }
/* ... */#else
if (sleep_us > 0) {
usleep(sleep_us);
}if (sleep_us > 0) { ... }
/* ... */#endif
te = eventLoop->timeEventHead;
maxId = eventLoop->timeEventNextId;
while (te) {
jim_wide id;
if (te->id > maxId) {
te = te->next;
continue;
}if (te->id > maxId) { ... }
if (JimGetTimeUsec(eventLoop) >= te->when) {
id = te->id;
Jim_RemoveTimeHandler(eventLoop, id);
te->timeProc(interp, te->clientData);
/* ... */
Jim_FreeTimeHandler(interp, te);
te = eventLoop->timeEventHead;
processed++;
}if (JimGetTimeUsec(eventLoop) >= te->when) { ... }
else {
te = te->next;
}else { ... }
}while (te) { ... }
return processed;
}{ ... }
static void JimELAssocDataDeleProc(Jim_Interp *interp, void *data)
{
void *next;
Jim_FileEvent *fe;
Jim_TimeEvent *te;
Jim_EventLoop *eventLoop = data;
fe = eventLoop->fileEventHead;
while (fe) {
next = fe->next;
if (fe->finalizerProc)
fe->finalizerProc(interp, fe->clientData);
Jim_Free(fe);
fe = next;
}while (fe) { ... }
te = eventLoop->timeEventHead;
while (te) {
next = te->next;
if (te->finalizerProc)
te->finalizerProc(interp, te->clientData);
Jim_Free(te);
te = next;
}while (te) { ... }
Jim_Free(data);
}{ ... }
static int JimELVwaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp);
Jim_Obj *oldValue;
int rc;
if (argc != 2) {
Jim_WrongNumArgs(interp, 1, argv, "name");
return JIM_ERR;
}if (argc != 2) { ... }
oldValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE);
if (oldValue) {
Jim_IncrRefCount(oldValue);
}if (oldValue) { ... }
else {
if (Jim_Length(Jim_GetResult(interp))) {
return JIM_ERR;
}if (Jim_Length(Jim_GetResult(interp))) { ... }
}else { ... }
eventLoop->suppress_bgerror = 0;
while ((rc = Jim_ProcessEvents(interp, JIM_ALL_EVENTS)) >= 0) {
Jim_Obj *currValue;
currValue = Jim_GetGlobalVariable(interp, argv[1], JIM_NONE);
/* ... */
if ((oldValue && !currValue) ||
(!oldValue && currValue) ||
(oldValue && currValue && !Jim_StringEqObj(oldValue, currValue)) ||
Jim_CheckSignal(interp)) {
break;
}if ((oldValue && !currValue) || (!oldValue && currValue) || (oldValue && currValue && !Jim_StringEqObj(oldValue, currValue)) || Jim_CheckSignal(interp)) { ... }
}while ((rc = Jim_ProcessEvents(interp, JIM_ALL_EVENTS)) >= 0) { ... }
if (oldValue)
Jim_DecrRefCount(interp, oldValue);
if (rc == -2) {
return JIM_ERR;
}if (rc == -2) { ... }
Jim_SetEmptyResult(interp);
return JIM_OK;
}{ ... }
static int JimELUpdateCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp);
static const char * const options[] = {
"idletasks", NULL
...};
enum { UPDATE_IDLE, UPDATE_NONE };
int option = UPDATE_NONE;
int flags = JIM_TIME_EVENTS;
if (argc == 1) {
flags = JIM_ALL_EVENTS;
}if (argc == 1) { ... }
else if (argc > 2 || Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
Jim_WrongNumArgs(interp, 1, argv, "?idletasks?");
return JIM_ERR;
}else if (argc > 2 || Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { ... }
eventLoop->suppress_bgerror = 0;
while (Jim_ProcessEvents(interp, flags | JIM_DONT_WAIT) > 0) {
}while (Jim_ProcessEvents(interp, flags | JIM_DONT_WAIT) > 0) { ... }
return JIM_OK;
}{ ... }
static void JimAfterTimeHandler(Jim_Interp *interp, void *clientData)
{
Jim_Obj *objPtr = clientData;
Jim_EvalObjBackground(interp, objPtr);
}{ ... }
static void JimAfterTimeEventFinalizer(Jim_Interp *interp, void *clientData)
{
Jim_Obj *objPtr = clientData;
Jim_DecrRefCount(interp, objPtr);
}{ ... }
static int JimELAfterCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_EventLoop *eventLoop = Jim_CmdPrivData(interp);
double ms = 0;
jim_wide id;
Jim_Obj *objPtr, *idObjPtr;
static const char * const options[] = {
"cancel", "info", "idle", NULL
...};
enum
{ AFTER_CANCEL, AFTER_INFO, AFTER_IDLE, AFTER_RESTART, AFTER_EXPIRE, AFTER_CREATE };
int option = AFTER_CREATE;
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "option ?arg ...?");
return JIM_ERR;
}if (argc < 2) { ... }
if (Jim_GetDouble(interp, argv[1], &ms) != JIM_OK) {
if (Jim_GetEnum(interp, argv[1], options, &option, "argument", JIM_ERRMSG) != JIM_OK) {
return JIM_ERR;
}if (Jim_GetEnum(interp, argv[1], options, &option, "argument", JIM_ERRMSG) != JIM_OK) { ... }
Jim_SetEmptyResult(interp);
}if (Jim_GetDouble(interp, argv[1], &ms) != JIM_OK) { ... }
else if (argc == 2) {
usleep(ms * 1000);
return JIM_OK;
}else if (argc == 2) { ... }
switch (option) {
case AFTER_IDLE:
if (argc < 3) {
Jim_WrongNumArgs(interp, 2, argv, "script ?script ...?");
return JIM_ERR;
}if (argc < 3) { ... }
case AFTER_IDLE:
case AFTER_CREATE: {
Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2);
Jim_IncrRefCount(scriptObj);
id = Jim_CreateTimeHandler(interp, (jim_wide)(ms * 1000), JimAfterTimeHandler, scriptObj,
JimAfterTimeEventFinalizer);
objPtr = Jim_NewStringObj(interp, NULL, 0);
Jim_AppendString(interp, objPtr, "after#", -1);
idObjPtr = Jim_NewIntObj(interp, id);
Jim_IncrRefCount(idObjPtr);
Jim_AppendObj(interp, objPtr, idObjPtr);
Jim_DecrRefCount(interp, idObjPtr);
Jim_SetResult(interp, objPtr);
return JIM_OK;
...}case AFTER_CREATE:
case AFTER_CANCEL:
if (argc < 3) {
Jim_WrongNumArgs(interp, 2, argv, "id|command");
return JIM_ERR;
}if (argc < 3) { ... }
else {
jim_wide remain = 0;
id = JimParseAfterId(argv[2]);
if (id <= 0) {
Jim_Obj *scriptObj = Jim_ConcatObj(interp, argc - 2, argv + 2);
id = JimFindAfterByScript(eventLoop, scriptObj);
Jim_FreeNewObj(interp, scriptObj);
if (id <= 0) {
break;
}if (id <= 0) { ... }
}if (id <= 0) { ... }
remain = Jim_DeleteTimeHandler(interp, id);
if (remain >= 0) {
Jim_SetResultInt(interp, remain);
}if (remain >= 0) { ... }
}else { ... }
break;
case AFTER_CANCEL:
case AFTER_INFO:
if (argc == 2) {
Jim_TimeEvent *te = eventLoop->timeEventHead;
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
char buf[30];
const char *fmt = "after#%" JIM_WIDE_MODIFIER;
while (te) {
snprintf(buf, sizeof(buf), fmt, te->id);
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, buf, -1));
te = te->next;
}while (te) { ... }
Jim_SetResult(interp, listObj);
}if (argc == 2) { ... }
else if (argc == 3) {
id = JimParseAfterId(argv[2]);
if (id >= 0) {
Jim_TimeEvent *e = JimFindTimeHandlerById(eventLoop, id);
if (e && e->timeProc == JimAfterTimeHandler) {
Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, listObj, e->clientData);
Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, e->initialus ? "timer" : "idle", -1));
Jim_SetResult(interp, listObj);
return JIM_OK;
}if (e && e->timeProc == JimAfterTimeHandler) { ... }
}if (id >= 0) { ... }
Jim_SetResultFormatted(interp, "event \"%#s\" doesn't exist", argv[2]);
return JIM_ERR;
}else if (argc == 3) { ... }
else {
Jim_WrongNumArgs(interp, 2, argv, "?id?");
return JIM_ERR;
}else { ... }
break;case AFTER_INFO:
}switch (option) { ... }
return JIM_OK;
}{ ... }
int Jim_eventloopInit(Jim_Interp *interp)
{
Jim_EventLoop *eventLoop;
Jim_PackageProvideCheck(interp, "eventloop");
eventLoop = Jim_Alloc(sizeof(*eventLoop));
memset(eventLoop, 0, sizeof(*eventLoop));
Jim_SetAssocData(interp, "eventloop", JimELAssocDataDeleProc, eventLoop);
Jim_CreateCommand(interp, "vwait", JimELVwaitCommand, eventLoop, NULL);
Jim_CreateCommand(interp, "update", JimELUpdateCommand, eventLoop, NULL);
Jim_CreateCommand(interp, "after", JimELAfterCommand, eventLoop, NULL);
return JIM_OK;
}{ ... }