Event loop in tclmain.c rewritten. New method searchStatus.
[ir-tcl-moved-to-github.git] / tclmain.c
1 /*
2  * IR toolkit for tcl/tk
3  * (c) Index Data 1995
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: tclmain.c,v $
7  * Revision 1.5  1995-03-20 08:53:30  adam
8  * Event loop in tclmain.c rewritten. New method searchStatus.
9  *
10  * Revision 1.4  1995/03/17  07:50:31  adam
11  * Headers have changed a little.
12  *
13  */
14
15 #include <sys/time.h>
16 #include <sys/types.h>
17 #include <assert.h>
18 #include <unistd.h>
19
20 #include <tcl.h>
21
22 #include "ir-tcl.h"
23
24 static char *fileName = NULL;
25
26 /* select(2) callbacks */
27 struct callback {
28     void (*r_handle)(void *p);
29     void (*w_handle)(void *p);
30     void (*x_handle)(void *p);
31     void *obj;
32 };
33 #define MAX_CALLBACK 200
34
35 static struct callback callback_table[MAX_CALLBACK];
36 static int max_fd = 3;            /* don't worry: it will grow... */
37
38 void tcl_mainloop (Tcl_Interp *interp, int interactive);
39
40 int Tcl_AppInit (Tcl_Interp *interp)
41 {
42     if (Tcl_Init(interp) == TCL_ERROR)
43         return TCL_ERROR;
44     if (ir_tcl_init(interp) == TCL_ERROR)
45         return TCL_ERROR;
46     return TCL_OK;
47 }
48
49 int main (int argc, char **argv)
50 {
51     Tcl_Interp *interp;
52     int code;
53     int i;
54
55     interp = Tcl_CreateInterp();
56     Tcl_SetVar (interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
57     if (argc == 2)
58         fileName = argv[1];
59
60     if (Tcl_AppInit(interp) != TCL_OK) {
61         fprintf(stderr, "Tcl_AppInit failed: %s\n", interp->result);
62     }
63     for (i=0; i<MAX_CALLBACK; i++)
64     {
65         callback_table[i].r_handle = NULL;
66         callback_table[i].w_handle = NULL;
67         callback_table[i].x_handle = NULL;
68     }
69     if (fileName)
70     {
71         code = Tcl_EvalFile (interp, fileName);
72         if (*interp->result != 0)
73             printf ("%s\n", interp->result);
74         if (code != TCL_OK)
75             exit (1);
76         tcl_mainloop (interp, 0);
77     }
78     else
79     {
80         Tcl_SetVar (interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
81         tcl_mainloop (interp, 1);
82     }
83     exit (0);
84 }
85
86 void tcl_mainloop (Tcl_Interp *interp, int interactive)
87 {
88     int i;
89     int res;
90     Tcl_DString command;
91     static fd_set fdset_tcl_r;
92     static fd_set fdset_tcl_w;
93     static fd_set fdset_tcl_x;
94     int min_fd;
95
96     min_fd = interactive ? 3 : 0;
97     if (interactive)
98     {
99         Tcl_DStringInit (&command);
100         printf ("[TCL]"); fflush (stdout);
101     }
102     while (1)
103     {
104         FD_ZERO (&fdset_tcl_r);
105         FD_ZERO (&fdset_tcl_w);
106         FD_ZERO (&fdset_tcl_x);
107         if (interactive)
108             FD_SET (0, &fdset_tcl_r);
109         for (res=0, i=min_fd; i<=max_fd; i++)
110         {
111             if (callback_table[i].w_handle)
112             {
113                 FD_SET (i, &fdset_tcl_w);
114                 res++;
115             }
116             if (callback_table[i].r_handle)
117             {
118                 FD_SET (i, &fdset_tcl_r);
119                 res++;
120             }
121             if (callback_table[i].x_handle)
122             {
123                 FD_SET (i, &fdset_tcl_x);
124                 res++;
125             }
126         }
127         if (!interactive && !res)
128             return;
129         if ((res = select(max_fd+1, &fdset_tcl_r, &fdset_tcl_w, 
130                           &fdset_tcl_x, 0)) < 0)
131         {
132             perror("select");
133             exit(1);
134         }
135         if (!res)
136             continue;
137         for (i=min_fd; i<=max_fd; i++)
138         {
139             if (FD_ISSET (i, &fdset_tcl_r))
140             {
141                 assert (callback_table[i].r_handle);
142                 (*callback_table[i].r_handle) (callback_table[i].obj);
143             }
144             if (FD_ISSET (i, &fdset_tcl_w))
145             {
146                 assert (callback_table[i].w_handle);
147                 (*callback_table[i].w_handle) (callback_table[i].obj);
148             }
149             if (FD_ISSET (i, &fdset_tcl_x))
150             {
151                 assert (callback_table[i].x_handle);
152                 (*callback_table[i].x_handle) (callback_table[i].obj);
153             }
154         }
155         if (interactive && FD_ISSET(0, &fdset_tcl_r))
156         {
157             char input_buf[256];
158             int count = read (0, input_buf, 256);
159
160             if (count <= 0)
161                 exit (0);
162             Tcl_DStringAppend (&command, input_buf, count);
163             if (Tcl_CommandComplete (Tcl_DStringValue (&command)))
164             {
165                 int code = Tcl_Eval (interp, Tcl_DStringValue (&command));
166                 Tcl_DStringFree (&command);
167                 if (code)
168                     printf ("[ERR:%s]\n", interp->result);
169                 else
170                     printf ("[RES:%s]\n", interp->result);
171                 printf ("[TCL]"); fflush (stdout);
172             }
173         }
174     }
175 }
176
177 void ir_select_add (int fd, void *obj)
178 {
179     callback_table[fd].obj = obj;
180     callback_table[fd].r_handle = ir_select_read;
181     callback_table[fd].w_handle = NULL;
182     callback_table[fd].x_handle = NULL;
183     if (fd > max_fd)
184         max_fd = fd;
185 }
186
187 void ir_select_add_write (int fd, void *obj)
188 {
189     callback_table[fd].w_handle = ir_select_write;
190     if (fd > max_fd)
191         max_fd = fd;
192 }
193
194 void ir_select_remove_write (int fd, void *obj)
195 {
196     callback_table[fd].w_handle = NULL;
197 }
198
199 void ir_select_remove (int fd, void *obj)
200 {
201     callback_table[fd].r_handle = NULL;
202     callback_table[fd].w_handle = NULL;
203     callback_table[fd].x_handle = NULL;
204 }