1*22168Sdist /* 2*22168Sdist * Copyright (c) 1980 Regents of the University of California. 3*22168Sdist * All rights reserved. The Berkeley software License Agreement 4*22168Sdist * specifies the terms and conditions for redistribution. 5*22168Sdist */ 6753Speter 714733Sthien #ifndef lint 8*22168Sdist static char sccsid[] = "@(#)func.c 5.1 (Berkeley) 06/05/85"; 9*22168Sdist #endif not lint 10753Speter 11*22168Sdist 12753Speter #include "whoami.h" 13753Speter #ifdef OBJ 14753Speter /* 15753Speter * the rest of the file 16753Speter */ 17753Speter #include "0.h" 18753Speter #include "tree.h" 19753Speter #include "opcode.h" 2014733Sthien #include "tree_ty.h" 21753Speter 22753Speter /* 23753Speter * Funccod generates code for 24753Speter * built in function calls and calls 25753Speter * call to generate calls to user 26753Speter * defined functions and procedures. 27753Speter */ 2814733Sthien struct nl 2914733Sthien *funccod(r) 3014733Sthien struct tnode *r; 31753Speter { 32753Speter struct nl *p; 33753Speter register struct nl *p1; 346595Smckusick struct nl *tempnlp; 3514733Sthien register struct tnode *al; 36753Speter register op; 3714733Sthien int argc; 3814733Sthien struct tnode *argv, tr, tr2; 39753Speter 40753Speter /* 41753Speter * Verify that the given name 42753Speter * is defined and the name of 43753Speter * a function. 44753Speter */ 4514733Sthien p = lookup(r->pcall_node.proc_id); 4614733Sthien if (p == NLNIL) { 4714733Sthien rvlist(r->pcall_node.arg); 4814733Sthien return (NLNIL); 49753Speter } 501197Speter if (p->class != FUNC && p->class != FFUNC) { 51753Speter error("%s is not a function", p->symbol); 5214733Sthien rvlist(r->pcall_node.arg); 5314733Sthien return (NLNIL); 54753Speter } 5514733Sthien argv = r->pcall_node.arg; 56753Speter /* 57753Speter * Call handles user defined 58753Speter * procedures and functions 59753Speter */ 60753Speter if (bn != 0) 61753Speter return (call(p, argv, FUNC, bn)); 62753Speter /* 63753Speter * Count the arguments 64753Speter */ 65753Speter argc = 0; 6614733Sthien for (al = argv; al != TR_NIL; al = al->list_node.next) 67753Speter argc++; 68753Speter /* 69753Speter * Built-in functions have 70753Speter * their interpreter opcode 71753Speter * associated with them. 72753Speter */ 73753Speter op = p->value[0] &~ NSTAND; 74753Speter if (opt('s') && (p->value[0] & NSTAND)) { 75753Speter standard(); 76753Speter error("%s is a nonstandard function", p->symbol); 77753Speter } 78753Speter switch (op) { 79753Speter /* 80753Speter * Parameterless functions 81753Speter */ 82753Speter case O_CLCK: 83753Speter case O_SCLCK: 84753Speter case O_WCLCK: 85753Speter case O_ARGC: 86753Speter if (argc != 0) { 87753Speter error("%s takes no arguments", p->symbol); 88753Speter rvlist(argv); 8914733Sthien return (NLNIL); 90753Speter } 9114733Sthien (void) put(1, op); 92753Speter return (nl+T4INT); 93753Speter case O_EOF: 94753Speter case O_EOLN: 95753Speter if (argc == 0) { 9614733Sthien argv = (&tr); 9714733Sthien tr.list_node.list = (&tr2); 9814733Sthien tr2.tag = T_VAR; 9914733Sthien tr2.var_node.cptr = input->symbol; 10014733Sthien tr2.var_node.line_no = NIL; 10114733Sthien tr2.var_node.qual = TR_NIL; 102753Speter argc = 1; 103753Speter } else if (argc != 1) { 104753Speter error("%s takes either zero or one argument", p->symbol); 105753Speter rvlist(argv); 10614733Sthien return (NLNIL); 107753Speter } 108753Speter } 109753Speter /* 110753Speter * All other functions take 111753Speter * exactly one argument. 112753Speter */ 113753Speter if (argc != 1) { 114753Speter error("%s takes exactly one argument", p->symbol); 115753Speter rvlist(argv); 11614733Sthien return (NLNIL); 117753Speter } 118753Speter /* 119753Speter * Evaluate the argmument 120753Speter */ 1212070Smckusic if (op == O_EOF || op == O_EOLN) 12214733Sthien p1 = stklval(argv->list_node.list, NIL ); 1232070Smckusic else 12414733Sthien p1 = stkrval(argv->list_node.list, NLNIL , (long) RREQ ); 12514733Sthien if (p1 == NLNIL) 12614733Sthien return (NLNIL); 127753Speter switch (op) { 12814733Sthien case 0: 12914733Sthien error("%s is an unimplemented 6000-3.4 extension", p->symbol); 13014733Sthien default: 13114733Sthien panic("func1"); 132753Speter case O_EXP: 133753Speter case O_SIN: 134753Speter case O_COS: 135753Speter case O_ATAN: 136753Speter case O_LN: 137753Speter case O_SQRT: 138753Speter case O_RANDOM: 139753Speter case O_EXPO: 140753Speter case O_UNDEF: 141753Speter if (isa(p1, "i")) 1422537Speter convert( nl+T4INT , nl+TDOUBLE); 143753Speter else if (isnta(p1, "d")) { 144753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 14514733Sthien return (NLNIL); 146753Speter } 14714733Sthien (void) put(1, op); 148753Speter if (op == O_UNDEF) 149753Speter return (nl+TBOOL); 150753Speter else if (op == O_EXPO) 151753Speter return (nl+T4INT); 152753Speter else 153753Speter return (nl+TDOUBLE); 154753Speter case O_SEED: 155753Speter if (isnta(p1, "i")) { 156753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 15714733Sthien return (NLNIL); 158753Speter } 15914733Sthien (void) put(1, op); 160753Speter return (nl+T4INT); 161753Speter case O_ROUND: 162753Speter case O_TRUNC: 163753Speter if (isnta(p1, "d")) { 164753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 16514733Sthien return (NLNIL); 166753Speter } 16714733Sthien (void) put(1, op); 168753Speter return (nl+T4INT); 169753Speter case O_ABS2: 170753Speter case O_SQR2: 171753Speter if (isa(p1, "d")) { 17214733Sthien (void) put(1, op + O_ABS8-O_ABS2); 173753Speter return (nl+TDOUBLE); 174753Speter } 175753Speter if (isa(p1, "i")) { 17614733Sthien (void) put(1, op + (width(p1) >> 2)); 177753Speter return (nl+T4INT); 178753Speter } 179753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 18014733Sthien return (NLNIL); 181753Speter case O_ORD2: 1829573Speter if (isa(p1, "bcis")) { 183753Speter return (nl+T4INT); 184753Speter } 1859573Speter if (classify(p1) == TPTR) { 1869573Speter if (!opt('s')) { 1879573Speter return (nl+T4INT); 1889573Speter } 1899573Speter standard(); 1909573Speter } 1919573Speter error("ord's argument must be of scalar type, not %s", 1929573Speter nameof(p1)); 19314733Sthien return (NLNIL); 194753Speter case O_SUCC2: 195753Speter case O_PRED2: 1962104Smckusic if (isa(p1, "d")) { 1972104Smckusic error("%s is forbidden for reals", p->symbol); 19814733Sthien return (NLNIL); 199753Speter } 2002104Smckusic if ( isnta( p1 , "bcsi" ) ) { 2012104Smckusic error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 2022104Smckusic return NIL; 2032104Smckusic } 2046595Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 205753Speter if (isa(p1, "i")) { 2063074Smckusic if (width(p1) <= 2) { 2072104Smckusic op += O_PRED24 - O_PRED2; 20814733Sthien (void) put(3, op, (int)tempnlp->range[0], 2096595Smckusick (int)tempnlp->range[1]); 2103074Smckusic } else { 211753Speter op++; 21214733Sthien (void) put(3, op, tempnlp->range[0], 2136595Smckusick tempnlp->range[1]); 2143074Smckusic } 2152104Smckusic return nl + T4INT; 2162104Smckusic } else { 21714733Sthien (void) put(3, op, (int)tempnlp->range[0], 2186595Smckusick (int)tempnlp->range[1]); 2192104Smckusic return p1; 220753Speter } 221753Speter case O_ODD2: 222753Speter if (isnta(p1, "i")) { 223753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 22414733Sthien return (NLNIL); 225753Speter } 22614733Sthien (void) put(1, op + (width(p1) >> 2)); 227753Speter return (nl+TBOOL); 228753Speter case O_CHR2: 229753Speter if (isnta(p1, "i")) { 230753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 23114733Sthien return (NLNIL); 232753Speter } 23314733Sthien (void) put(1, op + (width(p1) >> 2)); 234753Speter return (nl+TCHAR); 235753Speter case O_CARD: 2361553Speter if (isnta(p1, "t")) { 2371553Speter error("Argument to card must be a set, not %s", nameof(p1)); 23814733Sthien return (NLNIL); 239753Speter } 24014733Sthien (void) put(2, O_CARD, width(p1)); 241753Speter return (nl+T2INT); 242753Speter case O_EOLN: 243753Speter if (!text(p1)) { 244753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 24514733Sthien return (NLNIL); 246753Speter } 24714733Sthien (void) put(1, op); 248753Speter return (nl+TBOOL); 249753Speter case O_EOF: 250753Speter if (p1->class != FILET) { 251753Speter error("Argument to eof must be file, not %s", nameof(p1)); 25214733Sthien return (NLNIL); 253753Speter } 25414733Sthien (void) put(1, op); 255753Speter return (nl+TBOOL); 256753Speter } 257753Speter } 258753Speter #endif OBJ 259