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