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