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
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
16 #if (!defined(lint) && !defined(SABER))
17 static const char rcsid_node_c[] = "$Id$";
20 #include <zephyr/mit-copyright.h>
22 #include "new_memory.h"
25 /****************************************************************************/
27 /* Internal node construction & destruction functions: */
29 /****************************************************************************/
32 * NODE_BATCH_SIZE - the number of nodes to malloc at once to save overhead:
35 #define NODE_BATCH_SIZE 100
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.
45 static struct _bunch_of_nodes {
46 struct _bunch_of_nodes *next_bunch;
47 Node nodes[NODE_BATCH_SIZE];
49 static struct _bunch_of_nodes *current_bunch = NULL;
50 static int last_node_in_current_bunch_used = -1;
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.
64 node_create(int opcode)
70 * Handle special case where no nodes allocated yet:
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;
79 * If all nodes allocated so far in use, allocate another
80 * bunch of NODE_BATCH_SIZE nodes:
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;
91 * Get next not already used node & ready it for use:
93 last_node_in_current_bunch_used++;
94 result = &(current_bunch->nodes[last_node_in_current_bunch_used]);
95 result->opcode = opcode;
106 node_DestroyAllNodes(void)
108 struct _bunch_of_nodes *next_bunch;
109 int i, last_node_used_in_this_bunch;
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);
127 current_bunch = nodes;
130 /****************************************************************************/
132 /* Node construction functions: */
134 /****************************************************************************/
137 node_create_string_constant(int opcode,
142 n = node_create(opcode);
143 n->d.string_constant = text;
148 node_create_noary(int opcode)
152 n = node_create(opcode);
157 node_create_unary(int opcode,
162 n = node_create(opcode);
163 n->d.nodes.first = arg;
168 node_create_binary(int opcode,
174 n = node_create(opcode);
175 n->d.nodes.first = first_arg;
176 n->d.nodes.second = second_arg;
180 /****************************************************************************/
182 /* Node utility functions: */
184 /****************************************************************************/
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.
196 reverse_list_of_nodes(Node *list)
202 next_node = list->next;
205 * Add the node list to the beginning of linked list head:
216 /****************************************************************************/
218 /* Node display functions: */
220 /****************************************************************************/
225 print_stuff(Node *node,
226 string format_string)
230 for (c=(*(format_string++)); c; c=(*(format_string++))) {
235 c=(*(format_string++));
241 printf("%s", node->d.string_constant);
243 node_display(node->d.nodes.first);
245 node_display(node->d.nodes.second);
251 static string how_to_print[] = {
252 "\"%s\"", /* constant string */
292 "appendport %1 %2\n",
295 "outputport %1 %2\n",
304 "case %1\n%2endcase\n",
305 "while %1 do\n%2endwhile\n",
310 "elseif %1 then\n%2",
315 void node_display(Node *node)
317 int opcode = LAST_EXPR_OPCODE + 1;
319 for (; node; node=node->next) {
320 if (opcode<=LAST_EXPR_OPCODE)
323 opcode = node->opcode;
324 if (opcode>=0 && opcode<NUMBER_OF_OPCODES)
325 print_stuff(node, how_to_print[opcode]);
327 printf("[opcode %d]", opcode);