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