C:/Users/Dennis/src/lang/bertrand/BERTRAND/bertrand/ops.c

Go to the documentation of this file.
00001 /********************************************************************
00002  *
00003  * Manage operator nodes.
00004  *
00005  * Entry points are "op_new" to allocate an operator node,
00006  * and "op_mem_free" to free all operator memory.
00007  * Other entry points are for debugging.
00008  *
00009  ********************************************************************/
00010 
00011 #include "def.h"
00012 
00013 /* linked lists that hold operators definitions */
00014 OP *single_op = NULL;   /* list of single-character operators */
00015 OP *double_op = NULL;   /* list of double-character operators */
00016 OP *name_op = NULL;     /* list of alphanumeric operators */
00017 OP *type_op = NULL;     /* list of types */
00018 
00019 #define OP_BYTES 1024   /* number of operator bytes to allocate */
00020 static char *op_mem = NULL;             /* operator memory */
00021 static int free_byte = OP_BYTES;        /* next free byte */
00022 
00023 /* VERY MACHINE DEPENDENT */
00024 #define ALIGN 4         /* align op nodes on 4 byte boundaries */
00025 
00026 /********************************************************************
00027  *
00028  * Allocate memory for operator nodes.
00029  * Size of node depends upon length of operator name, but will always
00030  * be a multiple of 4 bytes.  This is very machine dependent.
00031  * 68000 only requires even byte alignment.  Other machines
00032  * may require size to be a some other multiple of 2.
00033  *
00034  * entry:       length of operator name.
00035  *
00036  * exit:        address of operator node returned
00037  *
00038  ********************************************************************/
00039 OP *
00040 op_new(pl)
00041 int pl;         /* length of print name (not counting null) */
00042 {
00043 char *malloc();
00044 int asize;      /* number of bytes to allocate */
00045 OP *op;
00046 
00047 asize = sizeof(OP) + pl;        /* includes added space for null */
00048 if ((asize % ALIGN) != 0) asize += ALIGN - (asize % ALIGN);
00049 #ifdef DEBUG
00050 printf("allocating operator node of %d bytes\n", asize);
00051 fflush(stdout);
00052 #endif
00053 
00054 if (asize > OP_BYTES - free_byte) {
00055     char *old_op_mem = op_mem;
00056     op_mem = malloc(OP_BYTES); 
00057     if (!op_mem) error("out of memory");
00058     ((char **) op_mem)[0] = old_op_mem; /* first word points to old memory */
00059     free_byte = sizeof(char *);         /* skip first word */
00060 #   ifdef DEBUG
00061     printf("allocated operator node memory\n");
00062 #   endif
00063     }
00064 op = (OP *) (op_mem + free_byte);
00065 free_byte += asize;
00066 op->length = (unsigned char) pl;
00067 op->eval = 0;
00068 op->hash = (RULE *) NULL;
00069 op->super = (OP *) NULL;
00070 op->other = (OP *) NULL;
00071 return op;
00072 }
00073 
00074 /********************************************************************
00075  *
00076  * Free all operator node memory.
00077  *
00078  * This will also free all rules associated with the operators.
00079  *
00080  ********************************************************************/
00081 void
00082 op_mem_free()
00083 {
00084 char *next_op_mem;
00085 void rule_free();       /* from rules.c */
00086 void free();
00087 int asize;
00088 
00089 register int fpos;
00090 register RULE *rr;
00091 
00092 while (op_mem) {
00093     next_op_mem = *((char **) op_mem);
00094     fpos = sizeof(char *);
00095     while (fpos<free_byte) {
00096         rr = ((OP *)(op_mem+fpos))->hash;
00097         while(rr) {
00098             rule_free(rr);
00099             rr = rr->next;
00100             }
00101         asize = sizeof(OP) + ((OP *)(op_mem+fpos))->length;
00102         if ((asize % ALIGN) != 0) asize += ALIGN - (asize % ALIGN);
00103         fpos += asize;
00104         }
00105     free(op_mem);
00106     op_mem = next_op_mem;
00107     }
00108 free_byte = OP_BYTES;   /* to indicate no memory allocated */
00109 single_op = NULL;       /* no single-character operators */
00110 double_op = NULL;       /* no double-character operators */
00111 name_op = NULL;         /* no alphanumeric operators */
00112 type_op = NULL;         /* no types */
00113 }
00114 
00115 /********************************************************************
00116  *
00117  * Depending on the type of operator, insert node into appropriate 
00118  * list in alphabetical order.  (Infix version of an operator precedes
00119  * its unary version.)
00120  * Make sure that this operator is not a duplicate of another
00121  * operator with the same arity.  If the operator has the same
00122  * name as an operator of a different arity (one binary, one unary),
00123  * link the two together using the "other" field.
00124  *
00125  * entry:       Pointer to pointer to appropriate op node list.
00126  *              Pointer to operator node to be inserted.
00127  * 
00128  * exit:        Node has been linked to appropriate list; 
00129  *               if it is the first node in the list, the head of
00130  *               the list points to it; error routine is called
00131  *               if it is a duplicate operator.
00132  *
00133  ********************************************************************/
00134 void
00135 op_put(oplist, op)
00136 OP **oplist;                    /* pointer to pointer to op node list */
00137 OP *op;                         /* pointer to oper node to be inserted */
00138 {
00139 int val;                        /* lexical comparison of operator names */
00140 register OP *curr_op = *oplist; /* pointer to op node list to insert in */
00141 register OP *prev_op = NULL;    /* pointer to previous op node in list */
00142 char *arity_name();             /* printable form of arity (in this file) */
00143 
00144 /* Insert into list curr_op */
00145 
00146 if (curr_op == NULL) {          /* list is empty */
00147     op->next = NULL;
00148     *oplist = op;                       /* set pointer to top of list */
00149     return;
00150     }
00151 
00152 /* insert in alphabetical order */
00153 while (curr_op) {
00154 
00155    /* compare operator names */
00156    val = strcmp(curr_op->pname, op->pname);
00157 
00158    /* If two operator names are identical, link them together.
00159       If their arities are also identical, then it is an error. 
00160       If current operator is infix, insert it now and return;
00161       otherwise, the operator is unary so wait until we have
00162       passed the infix operator and insert it then. */
00163 
00164    if (val == 0) {
00165         curr_op->other = op;
00166         op->other = curr_op;
00167         if (op->arity & BINARY) {
00168             val = 1;    /* force > 0, so will insert now */
00169             if (!(curr_op->arity & UNARY)) {
00170                 fprintf(stderr, "existing operator: %s", curr_op->pname);
00171                 fprintf(stderr, ", arity: %s\n", arity_name(curr_op->arity));
00172                 fprintf(stderr, "input operator: %s", op->pname);
00173                 fprintf(stderr, ", arity: %s\n", arity_name(op->arity));
00174                 fprintf(stderr, "duplicate operator is binary\n");
00175                 fprintf(stderr, "current operator must be unary\n");
00176                 error("invalid duplicate operators");
00177                 }
00178             }
00179         else if (op->arity & UNARY) {
00180             /* if op is UNARY, then will get it on next time through */
00181             if (!(curr_op->arity & BINARY)) {
00182                 fprintf(stderr, "existing operator: %s", curr_op->pname);
00183                 fprintf(stderr, ", arity: %s\n", arity_name(curr_op->arity));
00184                 fprintf(stderr, "input operator: %s", op->pname);
00185                 fprintf(stderr, ", arity: %s\n", arity_name(op->arity));
00186                 fprintf(stderr, "duplicate operator is unary\n");
00187                 fprintf(stderr, "current operator must be binary\n");
00188                 error("invalid duplicate operators");
00189                 }
00190             }
00191         else {
00192             fprintf(stderr, "existing operator: %s", curr_op->pname);
00193             fprintf(stderr, ", arity: %s\n", arity_name(curr_op->arity));
00194             fprintf(stderr, "input operator: %s", op->pname);
00195             fprintf(stderr, ", arity: %s\n", arity_name(op->arity));
00196             fprintf(stderr, "operators with the same name may only be");
00197             fprintf(stderr, " unary and binary (one of each).\n");
00198             error("invalid duplicate operators");
00199             }
00200         }       /* end of duplicate operators */
00201 
00202     if (val > 0) {              /* insert here, and return */
00203         op->next = curr_op;
00204         if (prev_op)            /* middle of list */
00205            prev_op->next = op;
00206         else                    /* top of list */
00207            *oplist = op;
00208         return;
00209         }
00210     /* otherwise, look at next node in list */
00211     prev_op = curr_op;
00212     curr_op = curr_op->next;
00213     }                           /* end of while loop */
00214     
00215 /* hit end of list */
00216 prev_op->next = op;
00217 op->next = NULL;
00218 }
00219 
00220 /********************************************************************
00221  *
00222  * Routines to print debugging information.
00223  *
00224  ********************************************************************/
00225 
00226 /********************************************************************
00227  *
00228  * Format an arity field for printing.
00229  *
00230  * entry:       Numeric arity value, see def.h
00231  *
00232  * exit:        String containing print value of arity.
00233  *              Error condition if invalid arity (shouldn't happen).
00234  *
00235  ********************************************************************/
00236 char *
00237 arity_name(arity)
00238 short arity;
00239 {
00240 static char buf[80];
00241 
00242 switch(arity) {
00243  case NONASSOC: return("binary nonassociative");
00244  case LEFT:     return("binary left associative");
00245  case RIGHT:    return("binary right associative");
00246  case PREFIX:   return("unary prefix");
00247  case POSTFIX:  return("unary postfix");
00248  case OUTFIX1:  return("unary outfix1");
00249  case OUTFIX2:  return("unary outfix2");
00250  case NULLARY:  return("nullary");
00251  case UNARY:    return("unary");
00252  case BINARY:   return("binary");
00253  case OP_NAME:  return("name or type");
00254  case OP_NUM:   return("number");
00255  case OP_STR:   return("string");
00256  default:       sprintf(buf, "unknown arity/associativity: 0x%x", arity);
00257                 return(buf);
00258     }
00259 }       /* end of arity_name */
00260 
00261 /********************************************************************
00262  *
00263  * Print a single linked list containing operators.
00264  *
00265  ********************************************************************/
00266 void
00267 op_list_print(op)
00268 OP *op;
00269 {
00270     while (op) {
00271         fprintf(stderr, "operator: %s, ", op->pname);
00272         fprintf(stderr, "arity: %s, ", arity_name(op->arity));
00273         if (op->arity != OUTFIX1 && op->arity != OUTFIX2 &&
00274           op->arity != NULLARY)
00275             fprintf(stderr, "precedence: %ld\n", op->precedence);
00276         else fprintf(stderr, "\n");
00277         if (op->other) {
00278             fprintf(stderr, " linked to node whose operator is: %s ",
00279                 op->other->pname);
00280             fprintf(stderr, "and whose arity is: %s\n",
00281                 arity_name(op->other->arity));
00282             }
00283         op = op->next;
00284         }
00285     }
00286 
00287 /********************************************************************
00288  *
00289  * Print all of the linked lists containing operators (including types).
00290  *
00291  ********************************************************************/
00292 void
00293 ops_print()
00294 {
00295     fprintf(stderr, "\f");              /* form feed */
00296 
00297     /* Print single_op list */
00298     fprintf(stderr, "\nsingle special character operators:\n\n");
00299     op_list_print(single_op);
00300 
00301     /* Print double_op list */
00302     fprintf(stderr, "\ndouble special character operators:\n\n");
00303     op_list_print(double_op);
00304 
00305     /* Print name_op list */
00306     fprintf(stderr, "\nalphanumeric operators:\n\n");
00307     op_list_print(name_op);
00308 
00309     /* Print list of types */
00310     fprintf(stderr, "\ntypes (missing single quotes):\n\n");
00311     op_list_print(type_op);
00312     }           /* end of ops_print */

Generated on Fri Jan 25 09:58:43 2008 for Bertrand by  doxygen 1.5.4