adding zephyr-im master branch
This commit is contained in:
331
zwgc/node.c
Normal file
331
zwgc/node.c
Normal file
@ -0,0 +1,331 @@
|
||||
/* This file is part of the Project Athena Zephyr Notification System.
|
||||
* It is one of the source files comprising zwgc, the Zephyr WindowGram
|
||||
* client.
|
||||
*
|
||||
* Created by: Marc Horowitz <marc@athena.mit.edu>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 1989 by the Massachusetts Institute of Technology.
|
||||
* For copying and distribution information, see the file
|
||||
* "mit-copyright.h".
|
||||
*/
|
||||
|
||||
#include <sysdep.h>
|
||||
|
||||
#if (!defined(lint) && !defined(SABER))
|
||||
static const char rcsid_node_c[] = "$Id$";
|
||||
#endif
|
||||
|
||||
#include <zephyr/mit-copyright.h>
|
||||
|
||||
#include "new_memory.h"
|
||||
#include "node.h"
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Internal node construction & destruction functions: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* NODE_BATCH_SIZE - the number of nodes to malloc at once to save overhead:
|
||||
*/
|
||||
|
||||
#define NODE_BATCH_SIZE 100
|
||||
|
||||
/*
|
||||
* The nodes we have malloced are kept in a linked list of bunches of
|
||||
* NODE_BATCH_SIZE nodes. Nodes points to the first bunch on the list
|
||||
* and current_bunch to the last. All nodes from the first one in the first
|
||||
* bunch to the last_node_in_current_bunch_used'th one in the last bunch
|
||||
* are in use. The others have not been used yet.
|
||||
*/
|
||||
|
||||
static struct _bunch_of_nodes {
|
||||
struct _bunch_of_nodes *next_bunch;
|
||||
Node nodes[NODE_BATCH_SIZE];
|
||||
} *nodes = NULL;
|
||||
static struct _bunch_of_nodes *current_bunch = NULL;
|
||||
static int last_node_in_current_bunch_used = -1;
|
||||
|
||||
/*
|
||||
* Internal Routine:
|
||||
*
|
||||
* Node *node_create(int opcode)
|
||||
* Effects: Creates a node with opcode opcode and returns a pointer
|
||||
* to it. The next pointer of the returned node is NULL.
|
||||
* If the opcode is STRING_CONSTANT_OPCODE the caller must
|
||||
* ensure that the string_constant field points to a valid
|
||||
* string on the heap when node_DestroyAllNodes is called.
|
||||
*/
|
||||
|
||||
static Node *
|
||||
node_create(int opcode)
|
||||
{
|
||||
Node *result;
|
||||
|
||||
if (!nodes) {
|
||||
/*
|
||||
* Handle special case where no nodes allocated yet:
|
||||
*/
|
||||
current_bunch = nodes = (struct _bunch_of_nodes *)
|
||||
malloc(sizeof(struct _bunch_of_nodes));
|
||||
nodes->next_bunch = NULL;
|
||||
last_node_in_current_bunch_used = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If all nodes allocated so far in use, allocate another
|
||||
* bunch of NODE_BATCH_SIZE nodes:
|
||||
*/
|
||||
if (last_node_in_current_bunch_used == NODE_BATCH_SIZE-1) {
|
||||
current_bunch->next_bunch = (struct _bunch_of_nodes *)
|
||||
malloc(sizeof(struct _bunch_of_nodes));
|
||||
current_bunch = current_bunch->next_bunch;
|
||||
current_bunch->next_bunch = NULL;
|
||||
last_node_in_current_bunch_used = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get next not already used node & ready it for use:
|
||||
*/
|
||||
last_node_in_current_bunch_used++;
|
||||
result = &(current_bunch->nodes[last_node_in_current_bunch_used]);
|
||||
result->opcode = opcode;
|
||||
result->next = NULL;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
node_DestroyAllNodes(void)
|
||||
{
|
||||
struct _bunch_of_nodes *next_bunch;
|
||||
int i, last_node_used_in_this_bunch;
|
||||
|
||||
while (nodes) {
|
||||
next_bunch = nodes->next_bunch;
|
||||
last_node_used_in_this_bunch = next_bunch ?
|
||||
NODE_BATCH_SIZE-1 : last_node_in_current_bunch_used;
|
||||
for (i=0; i<=last_node_used_in_this_bunch; i++) {
|
||||
if (nodes->nodes[i].opcode==STRING_CONSTANT_OPCODE)
|
||||
free(nodes->nodes[i].d.string_constant);
|
||||
else if (nodes->nodes[i].opcode==VARREF_OPCODE)
|
||||
free(nodes->nodes[i].d.string_constant);
|
||||
else if (nodes->nodes[i].opcode==VARNAME_OPCODE)
|
||||
free(nodes->nodes[i].d.string_constant);
|
||||
}
|
||||
free(nodes);
|
||||
nodes = next_bunch;
|
||||
}
|
||||
|
||||
current_bunch = nodes;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Node construction functions: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
Node *
|
||||
node_create_string_constant(int opcode,
|
||||
string text)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = node_create(opcode);
|
||||
n->d.string_constant = text;
|
||||
return(n);
|
||||
}
|
||||
|
||||
Node *
|
||||
node_create_noary(int opcode)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = node_create(opcode);
|
||||
return(n);
|
||||
}
|
||||
|
||||
Node *
|
||||
node_create_unary(int opcode,
|
||||
Node *arg)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = node_create(opcode);
|
||||
n->d.nodes.first = arg;
|
||||
return(n);
|
||||
}
|
||||
|
||||
Node *
|
||||
node_create_binary(int opcode,
|
||||
Node *first_arg,
|
||||
Node *second_arg)
|
||||
{
|
||||
Node *n;
|
||||
|
||||
n = node_create(opcode);
|
||||
n->d.nodes.first = first_arg;
|
||||
n->d.nodes.second = second_arg;
|
||||
return(n);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Node utility functions: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
/*
|
||||
* Node *reverse_list_of_nodes(Node *list)
|
||||
* Modifies: the nodes on the linked list list
|
||||
* Effects: Reverses the linked list list and returns it.
|
||||
* This is done by modifing the next pointers of the
|
||||
* list elements to point to the previous node & returning
|
||||
* the address of the (previously) last node.
|
||||
*/
|
||||
|
||||
Node *
|
||||
reverse_list_of_nodes(Node *list)
|
||||
{
|
||||
Node *next_node;
|
||||
Node *head = NULL;
|
||||
|
||||
while (list) {
|
||||
next_node = list->next;
|
||||
|
||||
/*
|
||||
* Add the node list to the beginning of linked list head:
|
||||
*/
|
||||
list->next = head;
|
||||
head = list;
|
||||
|
||||
list = next_node;
|
||||
}
|
||||
|
||||
return(head);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* Node display functions: */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
static void
|
||||
print_stuff(Node *node,
|
||||
string format_string)
|
||||
{
|
||||
char c;
|
||||
|
||||
for (c=(*(format_string++)); c; c=(*(format_string++))) {
|
||||
if (c!='%') {
|
||||
putchar(c);
|
||||
continue;
|
||||
}
|
||||
c=(*(format_string++));
|
||||
if (!c) {
|
||||
format_string--;
|
||||
continue;
|
||||
}
|
||||
if (c=='s')
|
||||
printf("%s", node->d.string_constant);
|
||||
else if (c=='1')
|
||||
node_display(node->d.nodes.first);
|
||||
else if (c=='2')
|
||||
node_display(node->d.nodes.second);
|
||||
else
|
||||
putchar(c);
|
||||
}
|
||||
}
|
||||
|
||||
static string how_to_print[] = {
|
||||
"\"%s\"", /* constant string */
|
||||
"$%s", /* varref */
|
||||
"%s", /* varname */
|
||||
|
||||
"!%1",
|
||||
|
||||
"( %1 + %2 )",
|
||||
"( %1 and %2 )",
|
||||
"( %1 or %2 )",
|
||||
"( %1 == %2 )",
|
||||
"( %1 != %2 )",
|
||||
"( %1 =~ %2 )",
|
||||
"( %1 !~ %2 )",
|
||||
|
||||
"buffer()",
|
||||
|
||||
"substitute(%1)",
|
||||
"protect(%1)",
|
||||
"verbatim(%1)",
|
||||
"stylestrip(%1)",
|
||||
"getenv(%1)",
|
||||
"upcase(%1)",
|
||||
"downcase(%1)",
|
||||
"zvar(%1)",
|
||||
"get(%1)",
|
||||
|
||||
"lany(%1, %2)",
|
||||
"rany(%1, %2)",
|
||||
"lbreak(%1, %2)",
|
||||
"rbreak(%1, %2)",
|
||||
"lspan(%1, %2)",
|
||||
"rspan(%1, %2)",
|
||||
|
||||
"noop\n",
|
||||
"set %1 = %2\n",
|
||||
"fields %1\n",
|
||||
|
||||
"print %1\n",
|
||||
"clearbuf\n",
|
||||
|
||||
"appendport %1 %2\n",
|
||||
"execport %1 %2\n",
|
||||
"inputport %1 %2\n",
|
||||
"outputport %1 %2\n",
|
||||
"put %1 %2\n",
|
||||
"closeinput %1\n",
|
||||
"closeoutput %1\n",
|
||||
"closeport %1\n",
|
||||
|
||||
"exec %1 %2\n",
|
||||
|
||||
"%1endif\n",
|
||||
"case %1\n%2endcase\n",
|
||||
"while %1 do\n%2endwhile\n",
|
||||
"break\n",
|
||||
"exit\n",
|
||||
|
||||
"if %1 then\n%2",
|
||||
"elseif %1 then\n%2",
|
||||
"else\n%2",
|
||||
"match %1\n%2",
|
||||
"default\n%2" };
|
||||
|
||||
void node_display(Node *node)
|
||||
{
|
||||
int opcode = LAST_EXPR_OPCODE + 1;
|
||||
|
||||
for (; node; node=node->next) {
|
||||
if (opcode<=LAST_EXPR_OPCODE)
|
||||
printf(" ");
|
||||
|
||||
opcode = node->opcode;
|
||||
if (opcode>=0 && opcode<NUMBER_OF_OPCODES)
|
||||
print_stuff(node, how_to_print[opcode]);
|
||||
else
|
||||
printf("[opcode %d]", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user