]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/node.c
r4264@bucket (orig r254): kcr | 2008-01-20 22:11:44 -0500
[1ts-debian.git] / zephyr / zwgc / node.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It is one of the source files comprising zwgc, the Zephyr WindowGram
3  * client.
4  *
5  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
6  *
7  *      $Id$
8  *
9  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h".
12  */
13
14 #include <sysdep.h>
15
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_node_c[] = "$Id$";
18 #endif
19
20 #include <zephyr/mit-copyright.h>
21
22 #include "new_memory.h"
23 #include "node.h"
24
25 /****************************************************************************/
26 /*                                                                          */
27 /*            Internal node construction & destruction functions:           */
28 /*                                                                          */
29 /****************************************************************************/
30
31 /*
32  * NODE_BATCH_SIZE - the number of nodes to malloc at once to save overhead:
33  */
34
35 #define  NODE_BATCH_SIZE    100
36
37 /*
38  * The nodes we have malloced are kept in a linked list of bunches of
39  * NODE_BATCH_SIZE nodes.  Nodes points to the first bunch on the list
40  * and current_bunch to the last.  All nodes from the first one in the first
41  * bunch to the last_node_in_current_bunch_used'th one in the last bunch
42  * are in use.  The others have not been used yet.
43  */
44
45 static struct _bunch_of_nodes {
46     struct _bunch_of_nodes *next_bunch;
47     Node nodes[NODE_BATCH_SIZE];
48 } *nodes = NULL;
49 static struct _bunch_of_nodes *current_bunch = NULL;
50 static int last_node_in_current_bunch_used = -1;
51
52 /*
53  *  Internal Routine:
54  *
55  *    Node *node_create(int opcode)
56  *        Effects: Creates a node with opcode opcode and returns a pointer
57  *                 to it.  The next pointer of the returned node is NULL.
58  *                 If the opcode is STRING_CONSTANT_OPCODE the caller must
59  *                 ensure that the string_constant field points to a valid
60  *                 string on the heap when node_DestroyAllNodes is called.
61  */
62
63 static Node *
64 node_create(int opcode)
65 {
66     Node *result;
67
68     if (!nodes) {
69         /*
70          * Handle special case where no nodes allocated yet:
71          */
72         current_bunch = nodes = (struct _bunch_of_nodes *)
73           malloc(sizeof(struct _bunch_of_nodes));
74         nodes->next_bunch = NULL;
75         last_node_in_current_bunch_used = -1;
76     }
77
78     /*
79      * If all nodes allocated so far in use, allocate another
80      * bunch of NODE_BATCH_SIZE nodes:
81      */
82     if (last_node_in_current_bunch_used == NODE_BATCH_SIZE-1) {
83         current_bunch->next_bunch = (struct _bunch_of_nodes *)
84           malloc(sizeof(struct _bunch_of_nodes));
85         current_bunch = current_bunch->next_bunch;
86         current_bunch->next_bunch = NULL;
87         last_node_in_current_bunch_used = -1;
88     }
89
90     /*
91      * Get next not already used node & ready it for use:
92      */
93     last_node_in_current_bunch_used++;
94     result = &(current_bunch->nodes[last_node_in_current_bunch_used]);
95     result->opcode = opcode;
96     result->next = NULL;
97
98     return(result);
99 }
100
101 /*
102  *
103  */
104
105 void
106 node_DestroyAllNodes(void)
107 {
108     struct _bunch_of_nodes *next_bunch;
109     int i, last_node_used_in_this_bunch;
110
111     while (nodes) {
112         next_bunch = nodes->next_bunch;
113         last_node_used_in_this_bunch = next_bunch ?
114           NODE_BATCH_SIZE-1 : last_node_in_current_bunch_used;
115         for (i=0; i<=last_node_used_in_this_bunch; i++) {
116             if (nodes->nodes[i].opcode==STRING_CONSTANT_OPCODE)
117               free(nodes->nodes[i].d.string_constant);
118             else if (nodes->nodes[i].opcode==VARREF_OPCODE)
119               free(nodes->nodes[i].d.string_constant);
120             else if (nodes->nodes[i].opcode==VARNAME_OPCODE)
121               free(nodes->nodes[i].d.string_constant);
122         }
123         free(nodes);
124         nodes = next_bunch;
125     }
126
127     current_bunch = nodes;
128 }
129
130 /****************************************************************************/
131 /*                                                                          */
132 /*                     Node construction functions:                         */
133 /*                                                                          */
134 /****************************************************************************/
135
136 Node *
137 node_create_string_constant(int opcode,
138                             string text)
139 {
140     Node *n;
141
142     n = node_create(opcode);
143     n->d.string_constant = text;
144     return(n);
145 }
146
147 Node *
148 node_create_noary(int opcode)
149 {
150     Node *n;
151
152     n = node_create(opcode);
153     return(n);
154 }
155
156 Node *
157 node_create_unary(int opcode,
158                   Node *arg)
159 {
160     Node *n;
161
162     n = node_create(opcode);
163     n->d.nodes.first = arg;
164     return(n);
165 }
166
167 Node *
168 node_create_binary(int opcode,
169                    Node *first_arg,
170                    Node *second_arg)
171 {
172     Node *n;
173
174     n = node_create(opcode);
175     n->d.nodes.first = first_arg;
176     n->d.nodes.second = second_arg;
177     return(n);
178 }
179
180 /****************************************************************************/
181 /*                                                                          */
182 /*                        Node utility functions:                           */
183 /*                                                                          */
184 /****************************************************************************/
185
186 /*
187  *    Node *reverse_list_of_nodes(Node *list)
188  *        Modifies: the nodes on the linked list list
189  *        Effects: Reverses the linked list list and returns it.
190  *                 This is done by modifing the next pointers of the
191  *                 list elements to point to the previous node & returning
192  *                 the address of the (previously) last node.
193  */
194
195 Node *
196 reverse_list_of_nodes(Node *list)
197 {
198     Node *next_node;
199     Node *head = NULL;
200
201     while (list) {
202         next_node = list->next;
203
204         /*
205          * Add the node list to the beginning of linked list head:
206          */
207         list->next = head;
208         head = list;
209
210         list = next_node;
211     }
212
213     return(head);
214 }
215
216 /****************************************************************************/
217 /*                                                                          */
218 /*                        Node display functions:                           */
219 /*                                                                          */
220 /****************************************************************************/
221
222 #ifdef DEBUG
223
224 static void
225 print_stuff(Node *node,
226             string format_string)
227 {
228     char c;
229
230     for (c=(*(format_string++)); c; c=(*(format_string++))) {
231         if (c!='%') {
232             putchar(c);
233             continue;
234         }
235         c=(*(format_string++));
236         if (!c) {
237             format_string--;
238             continue;
239         }
240         if (c=='s')
241           printf("%s", node->d.string_constant);
242         else if (c=='1')
243           node_display(node->d.nodes.first);
244         else if (c=='2')
245           node_display(node->d.nodes.second);
246         else
247           putchar(c);
248     }
249 }
250
251 static string how_to_print[] = {
252     "\"%s\"",        /* constant string */
253     "$%s",           /* varref */
254     "%s",            /* varname */
255
256     "!%1",
257
258     "( %1 + %2 )",
259     "( %1 and %2 )",
260     "( %1 or %2 )",
261     "( %1 == %2 )",
262     "( %1 != %2 )",
263     "( %1 =~ %2 )",
264     "( %1 !~ %2 )",
265
266     "buffer()",
267     
268     "substitute(%1)",
269     "protect(%1)",
270     "verbatim(%1)",
271     "stylestrip(%1)",
272     "getenv(%1)",
273     "upcase(%1)",
274     "downcase(%1)",
275     "zvar(%1)",
276     "get(%1)",
277
278     "lany(%1, %2)",
279     "rany(%1, %2)",
280     "lbreak(%1, %2)",
281     "rbreak(%1, %2)",
282     "lspan(%1, %2)",
283     "rspan(%1, %2)",
284
285     "noop\n",
286     "set %1 = %2\n",
287     "fields %1\n",
288
289     "print %1\n",
290     "clearbuf\n",
291     
292     "appendport %1 %2\n",
293     "execport %1 %2\n",
294     "inputport %1 %2\n",
295     "outputport %1 %2\n",
296     "put %1 %2\n",
297     "closeinput %1\n",
298     "closeoutput %1\n",
299     "closeport %1\n",
300
301     "exec %1 %2\n",
302
303     "%1endif\n",
304     "case %1\n%2endcase\n",
305     "while %1 do\n%2endwhile\n",
306     "break\n",
307     "exit\n",
308     
309     "if %1 then\n%2",
310     "elseif %1 then\n%2",
311     "else\n%2",
312     "match %1\n%2",
313     "default\n%2" };
314
315 void node_display(Node *node)
316 {
317     int opcode = LAST_EXPR_OPCODE + 1;
318
319     for (; node; node=node->next) {
320         if (opcode<=LAST_EXPR_OPCODE)
321           printf(" ");
322
323         opcode = node->opcode;
324         if (opcode>=0 && opcode<NUMBER_OF_OPCODES)
325           print_stuff(node, how_to_print[opcode]);
326         else
327           printf("[opcode %d]", opcode);
328     }
329 }
330
331 #endif