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