Request queue.
[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.11  1995-08-03 13:23:02  adam
9  * Request queue.
10  *
11  * Revision 1.10  1995/06/30  12:39:28  adam
12  * Bug fix: loadFile didn't set record type.
13  * The MARC routines are a little less strict in the interpretation.
14  * Script display.tcl replaces the old marc.tcl.
15  * New interactive script: shell.tcl.
16  *
17  * Revision 1.9  1995/06/26  10:20:20  adam
18  * ir-tk works like wish.
19  *
20  * Revision 1.8  1995/06/21  15:16:44  adam
21  * More work on configuration.
22  *
23  * Revision 1.7  1995/06/21  11:04:54  adam
24  * Uses GNU autoconf 2.3.
25  * Install procedure implemented.
26  * boook bitmaps moved to sub directory bitmaps.
27  *
28  * Revision 1.6  1995/05/29  08:44:28  adam
29  * Work on delete of objects.
30  *
31  * Revision 1.5  1995/03/20  08:53:30  adam
32  * Event loop in tclmain.c rewritten. New method searchStatus.
33  *
34  * Revision 1.4  1995/03/17  07:50:31  adam
35  * Headers have changed a little.
36  *
37  */
38
39 #include <unistd.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #ifdef _AIX
43 #include <sys/select.h>
44 #endif
45 #include <assert.h>
46
47 #include <tcl.h>
48 #include <log.h>
49 #include "ir-tcl.h"
50
51 static char *fileName = NULL;
52
53 /* select(2) callbacks */
54 struct callback {
55     void (*r_handle)(void *p);
56     void (*w_handle)(void *p);
57     void (*x_handle)(void *p);
58     void *obj;
59 };
60 #define MAX_CALLBACK 200
61
62 static struct callback callback_table[MAX_CALLBACK];
63 static int max_fd = 3;            /* don't worry: it will grow... */
64
65 void tcl_mainloop (Tcl_Interp *interp, int interactive);
66
67 int Tcl_AppInit (Tcl_Interp *interp)
68 {
69     if (Tcl_Init(interp) == TCL_ERROR)
70         return TCL_ERROR;
71     if (ir_tcl_init(interp) == TCL_ERROR)
72         return TCL_ERROR;
73     return TCL_OK;
74 }
75
76 int main (int argc, char **argv)
77 {
78     Tcl_Interp *interp;
79     int code;
80     int i;
81
82     interp = Tcl_CreateInterp();
83     Tcl_SetVar (interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
84     if (argc == 2)
85         fileName = argv[1];
86
87     log_init (LOG_ALL, "", NULL);
88     if (Tcl_AppInit(interp) != TCL_OK) {
89         fprintf(stderr, "Tcl_AppInit failed: %s\n", interp->result);
90     }
91     for (i=0; i<MAX_CALLBACK; i++)
92     {
93         callback_table[i].r_handle = NULL;
94         callback_table[i].w_handle = NULL;
95         callback_table[i].x_handle = NULL;
96     }
97     if (fileName)
98     {
99         code = Tcl_EvalFile (interp, fileName);
100         if (*interp->result != 0)
101             printf ("%s\n", interp->result);
102         if (code != TCL_OK)
103             exit (1);
104         tcl_mainloop (interp, 0);
105     }
106     else if (isatty(0))
107     {
108
109         Tcl_SetVar (interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
110         tcl_mainloop (interp, 1);
111     }
112     else
113     {
114         Tcl_DString command;
115         char input_buf[1024];
116         int count;
117
118         printf ("xx\n");
119         Tcl_DStringInit (&command);
120         while (fgets (input_buf, 1024, stdin))
121         {
122             count = strlen(input_buf);
123             Tcl_DStringAppend (&command, input_buf, count);
124             if (Tcl_CommandComplete (Tcl_DStringValue (&command)))
125             {
126                 int code = Tcl_Eval (interp, Tcl_DStringValue (&command));
127                 Tcl_DStringFree (&command);
128                 if (code)
129                     printf ("Error: %s\n", interp->result);
130             }
131         }
132         tcl_mainloop (interp, 0);
133     }
134     exit (0);
135 }
136
137 void tcl_mainloop (Tcl_Interp *interp, int interactive)
138 {
139     int i;
140     int res;
141     Tcl_DString command;
142     static fd_set fdset_tcl_r;
143     static fd_set fdset_tcl_w;
144     static fd_set fdset_tcl_x;
145     int min_fd;
146
147     min_fd = interactive ? 3 : 0;
148     if (interactive)
149     {
150         Tcl_DStringInit (&command);
151         printf ("%% "); fflush (stdout);
152     }
153     while (1)
154     {
155         FD_ZERO (&fdset_tcl_r);
156         FD_ZERO (&fdset_tcl_w);
157         FD_ZERO (&fdset_tcl_x);
158         if (interactive)
159             FD_SET (0, &fdset_tcl_r);
160         for (res=0, i=min_fd; i<=max_fd; i++)
161         {
162             if (callback_table[i].w_handle)
163             {
164                 FD_SET (i, &fdset_tcl_w);
165                 res++;
166             }
167             if (callback_table[i].r_handle)
168             {
169                 FD_SET (i, &fdset_tcl_r);
170                 res++;
171             }
172             if (callback_table[i].x_handle)
173             {
174                 FD_SET (i, &fdset_tcl_x);
175                 res++;
176             }
177         }
178         if (!interactive && !res)
179             return;
180         if ((res = select(max_fd+1, &fdset_tcl_r, &fdset_tcl_w, 
181                           &fdset_tcl_x, 0)) < 0)
182         {
183             perror("select");
184             exit(1);
185         }
186         if (!res)
187             continue;
188         for (i=min_fd; i<=max_fd; i++)
189         {
190             if (FD_ISSET (i, &fdset_tcl_r))
191             {
192                 assert (callback_table[i].r_handle);
193                 (*callback_table[i].r_handle) (callback_table[i].obj);
194             }
195             if (FD_ISSET (i, &fdset_tcl_w))
196             {
197                 assert (callback_table[i].w_handle);
198                 (*callback_table[i].w_handle) (callback_table[i].obj);
199             }
200             if (FD_ISSET (i, &fdset_tcl_x))
201             {
202                 assert (callback_table[i].x_handle);
203                 (*callback_table[i].x_handle) (callback_table[i].obj);
204             }
205         }
206         if (interactive && FD_ISSET(0, &fdset_tcl_r))
207         {
208             char input_buf[1024];
209             int count = read (0, input_buf, 1024);
210
211             if (count <= 0)
212                 exit (0);
213             Tcl_DStringAppend (&command, input_buf, count);
214             if (Tcl_CommandComplete (Tcl_DStringValue (&command)))
215             {
216                 int code = Tcl_Eval (interp, Tcl_DStringValue (&command));
217                 Tcl_DStringFree (&command);
218                 if (code)
219                     printf ("Error: %s\n", interp->result);
220                 else if (*interp->result)
221                     printf ("%s\n", interp->result);
222                 printf ("%% "); fflush (stdout);
223             }
224         }
225     }
226 }
227
228 void ir_select_add (int fd, void *obj)
229 {
230     callback_table[fd].obj = obj;
231     callback_table[fd].r_handle = ir_select_read;
232     callback_table[fd].w_handle = NULL;
233     callback_table[fd].x_handle = NULL;
234     if (fd > max_fd)
235         max_fd = fd;
236 }
237
238 void ir_select_add_write (int fd, void *obj)
239 {
240     callback_table[fd].w_handle = ir_select_write;
241     if (fd > max_fd)
242         max_fd = fd;
243 }
244
245 void ir_select_remove_write (int fd, void *obj)
246 {
247     callback_table[fd].w_handle = NULL;
248 }
249
250 void ir_select_remove (int fd, void *obj)
251 {
252     callback_table[fd].r_handle = NULL;
253     callback_table[fd].w_handle = NULL;
254     callback_table[fd].x_handle = NULL;
255 }