///<param name = "**line"> Line to parse </param> static INPparseNode *PTparse(char **line) { PTelement stack[PT_STACKSIZE]; int sp = 0, st, i; PTelement *top, *next; INPparseNode *pn, *lpn, *rpn; stack[0].token = TOK_END; next = PTlexer(line); while ((sp > 1) || (next->token != TOK_END)) { /* Find the top-most terminal. */ i = sp; do { top = &stack[i--]; } while (top->token == TOK_VALUE); switch (prectable[top->token][next->token]) { case L: case E: /* Push the token read. */ if (sp == (PT_STACKSIZE - 1)) { fprintf(stderr, "Error: stack overflow\n"); return (NULL); } bcopy((char *)next, (char *)&stack[++sp], sizeof(PTelement)); next = PTlexer(line); continue; case R: fprintf(stderr, "Syntax error.\n"); return (NULL); case G: /* Reduce. Make st and sp point to the elts on the * stack at the end and beginning of the junk to * reduce, then try and do some stuff. When scanning * back for a <, ignore VALUES. */ st = sp; if (stack[sp].token == TOK_VALUE) sp--; while (sp > 0) { if (stack[sp - 1].token == TOK_VALUE) i = 2; /* No 2 pnodes together... */ else i = 1; if (prectable[stack[sp - i].token][stack[sp].token] == L) break; else sp = sp - i; } if (stack[sp - 1].token == TOK_VALUE) sp--; /* Now try and see what we can make of this. * The possibilities are: - node * node op node * ( node ) * func ( node ) * func ( node, node, node, ... ) <- new * node */ if (st == sp) { pn = makepnode(&stack[st]); if (pn == NULL) goto err; } else if ((stack[sp].token == TOK_UMINUS) && (st == sp + 1)) { lpn = makepnode(&stack[st]); if (lpn == NULL) goto err;// TODO: Remove GOTO pn = mkfnode("-", lpn); } else if ((stack[sp].token == TOK_LPAREN) && (stack[st].token == TOK_RPAREN)) { pn = makepnode(&stack[sp + 1]); if (pn == NULL) goto err;// TODO: Remove GOTO } else if ((stack[sp + 1].token == TOK_LPAREN) && (stack[st].token == TOK_RPAREN)) { lpn = makepnode(&stack[sp + 2]); if ((lpn == NULL) || (stack[sp].type != TYP_STRING)) goto err;// TODO: Remove GOTO if (!(pn = mkfnode(stack[sp].value.string, lpn))) return (NULL); } else { /* node op node */ lpn = makepnode(&stack[sp]); rpn = makepnode(&stack[st]); if ((lpn == NULL) || (rpn == NULL)) goto err;// TODO: Remove GOTO pn = mkbnode(stack[sp + 1].token, lpn, rpn); } stack[sp].token = TOK_VALUE; stack[sp].type = TYP_PNODE; stack[sp].value.pnode = pn; continue; } } pn = makepnode(&stack[1]); if (pn) return (pn); err: fprintf(stderr, "Syntax error.\n"); return (NULL); }
///<param name = "*fname"> The name of the function </param> ///<param name = "*arg"> The argument it is given </param> static INPparseNode *mkfnode(char *fname, INPparseNode *arg) { int i; INPparseNode *p = NULL; char buf[128], *name = NULL, *s = NULL; IFvalue temp; temp.nValue = 0;// this line is required by microsoft. Generates a C4700 error if this is not included /* Make sure the case is ok. */ (void)strcpy(buf, fname); for (s = buf; *s; s++) { if (isupper(*s)) { *s = tolower(*s); } } p = (INPparseNode *)MALLOC(sizeof(INPparseNode)); if (!strcmp(buf, "v")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) { strcpy(name, arg->funcname); } else if (arg->type == PT_CONSTANT) { (void)sprintf(name, "%d", (int)arg->constant); } else if (arg->type != PT_COMMA) { fprintf(stderr, "Error: badly formed node voltage\n"); return (NULL); } if (arg->type == PT_COMMA) { /* Change v(a,b) into v(a) - v(b) */ p = mkb(PT_MINUS, mkfnode(fname, arg->left), mkfnode(fname, arg->right)); } else { /* printf("getting a node called '%s'\n", name); */ INPtermInsert(circuit, &name, tables, &(temp.nValue)); /* This block is reallocating the value variable. Although defined as a pointer, it is actually being used as a dynamic array*/ for (i = 0; i < numvalues; i++) { if ((types[i] == IF_NODE) && (values[i].nValue == temp.nValue)) break; } if (i == numvalues) { if (numvalues) { /*This is a test*/ values = (IFvalue *)REALLOC((char *)values, (numvalues + 1) * sizeof(IFvalue)); /* values is becoming an array where each element is IFvalue. Dynamic Array Allocation */ types = (int *)REALLOC((char *)types, (numvalues + 1) * sizeof(int)); } else { /* If numvalues is 0, then the program will allocate values with 1 cell The program will only execute this block once */ values = (IFvalue *)MALLOC(sizeof(IFvalue)); /* values is becoming an array where each element is IFvalue */ types = (int *)MALLOC(sizeof(int)); } values[i] = temp; types[i] = IF_NODE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } } else if (!strcmp(buf, "i")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) strcpy(name, arg->funcname); else if (arg->type == PT_CONSTANT) (void) sprintf(name, "%d", (int)arg->constant); else { fprintf(stderr, "Error: badly formed branch current\n"); return (NULL); } /* printf("getting a device called '%s'\n", name); */ INPinsert(&name, tables); for (i = 0; i < numvalues; i++) { if ((types[i] == IF_INSTANCE) && (values[i].uValue == temp.uValue)) break; } if (i == numvalues) { if (numvalues) { values = (IFvalue *)REALLOC((char *)values, (numvalues + 1) * sizeof(IFvalue)); types = (int *)REALLOC((char *)types, (numvalues + 1) * sizeof(int)); } else { values = (IFvalue *)MALLOC(sizeof(IFvalue)); types = (int *)MALLOC(sizeof(int)); } values[i].uValue = (IFuid)name; types[i] = IF_INSTANCE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } else { for (i = 0; i < NUM_FUNCS; i++) { if (!strcmp(funcs[i].name, buf)) break; } if (i == NUM_FUNCS) { fprintf(stderr, "Error: no such function '%s'\n", buf); return (NULL); } p->type = PT_FUNCTION; p->left = arg; p->funcname = funcs[i].name; p->funcnum = funcs[i].number; p->function = funcs[i].funcptr; } return (p); }
static INPparseNode *mkfnode(char *fname, INPparseNode * arg) { int i; INPparseNode *p; char buf[128], *name, *s; IFvalue temp; /* Make sure the case is ok. */ (void) strcpy(buf, fname); for (s = buf; *s; s++) if (isupper(*s)) *s = tolower(*s); p = (INPparseNode *) MALLOC(sizeof(INPparseNode)); if (!strcmp(buf, "v")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) { strcpy(name, arg->funcname); } else if (arg->type == PT_CONSTANT) { (void) sprintf(name, "%d", (int) arg->constant); } else if (arg->type != PT_COMMA) { fprintf(stderr, "Error: badly formed node voltage\n"); return (NULL); } if (arg->type == PT_COMMA) { /* Change v(a,b) into v(a) - v(b) */ p = mkb(PT_MINUS, mkfnode(fname, arg->left), mkfnode(fname, arg->right)); } else { /* printf("getting a node called '%s'\n", name); */ INPtermInsert(circuit, &name, tables, &(temp.nValue)); for (i = 0; i < numvalues; i++) if ((types[i] == IF_NODE) && (values[i].nValue == temp.nValue)) break; if (i == numvalues) { if (numvalues) { values = (IFvalue *) REALLOC((char *) values, (numvalues + 1) * sizeof(IFvalue)); types = (int *) REALLOC((char *) types, (numvalues + 1) * sizeof(int)); } else { values = (IFvalue *) MALLOC(sizeof(IFvalue)); types = (int *) MALLOC(sizeof(int)); } values[i] = temp; types[i] = IF_NODE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } } else if (!strcmp(buf, "i")) { name = MALLOC(128); if (arg->type == PT_PLACEHOLDER) strcpy(name, arg->funcname); else if (arg->type == PT_CONSTANT) (void) sprintf(name, "%d", (int) arg->constant); else { fprintf(stderr, "Error: badly formed branch current\n"); return (NULL); } /* printf("getting a device called '%s'\n", name); */ INPinsert(&name, tables); for (i = 0; i < numvalues; i++) if ((types[i] == IF_INSTANCE) && (values[i].uValue == temp.uValue)) break; if (i == numvalues) { if (numvalues) { values = (IFvalue *) REALLOC((char *) values, (numvalues + 1) * sizeof(IFvalue)); types = (int *) REALLOC((char *) types, (numvalues + 1) * sizeof(int)); } else { values = (IFvalue *) MALLOC(sizeof(IFvalue)); types = (int *) MALLOC(sizeof(int)); } values[i].uValue = (IFuid) name; types[i] = IF_INSTANCE; numvalues++; } p->valueIndex = i; p->type = PT_VAR; } else { for (i = 0; i < NUM_FUNCS; i++) if (!strcmp(funcs[i].name, buf)) break; if (i == NUM_FUNCS) { fprintf(stderr, "Error: no such function '%s'\n", buf); return (NULL); } p->type = PT_FUNCTION; p->left = arg; p->funcname = funcs[i].name; p->funcnum = funcs[i].number; p->function = funcs[i].funcptr; } return (p); }