void ASTfunction_call::typecheck_builtin_specialcase () { if (m_name == "transform") { // Special case for transform: under the covers, it selects // vector or normal special versions depending on its use. if (typespec().simpletype() == TypeDesc::TypeVector) m_name = ustring ("transformv"); else if (typespec().simpletype() == TypeDesc::TypeNormal) m_name = ustring ("transformn"); } // Void functions DO read their first arg, DON'T write it if (typespec().is_void()) { argread (0, true); argwrite (0, false); } if (func()->readwrite_special_case()) { if (m_name == "fresnel") { // This function has some output args argwriteonly (3); argwriteonly (4); argwriteonly (5); argwriteonly (6); } else if (m_name == "sincos") { argwriteonly (1); argwriteonly (2); } else if (m_name == "getattribute" || m_name == "getmessage" || m_name == "gettextureinfo" || m_name == "dict_value") { // these all write to their last argument argwriteonly ((int)listlength(args())); } else if (func()->texture_args()) { // texture-like function, look out for "alpha" std::vector<ASTNode::ref> argvec; list_to_vec (args(), argvec); // Find the beginning of the optional arguments -- it will be // the first string argument AFTER the filename. int nargs = (int) listlength(args()); int firstopt = 2; while (firstopt < nargs && ! argvec[firstopt]->typespec().is_string()) ++firstopt; // Loop through the optional args, look for "alpha" for (int a = firstopt; a < (int)argvec.size()-1; a += 2) { ASTNode *s = argvec[a].get(); if (s->typespec().is_string() && s->nodetype() == ASTNode::literal_node && ! strcmp (((ASTliteral *)s)->strval(), "alpha")) { // 'alpha' writes to the next arg! if (a+2 < 32) argwriteonly (a+2); // mark writeable else { // We can only designate the first 32 args // writeable. So swap it with earlier optional args. std::swap (argvec[firstopt], argvec[a]); std::swap (argvec[firstopt+1], argvec[a+1]); argwriteonly (firstopt+1); firstopt += 2; // advance in case another is needed } } } m_children[0] = vec_to_list (argvec); } } if (func()->takes_derivs()) { // Special handling for the few functions that take derivatives // of their arguments. Mark those with argtakesderivs. // N.B. This counts arguments in the same way that opcodes do -- // assuming "arg 0" is the return value. size_t nargs = listlength(args()); if (m_name == "area") { argtakesderivs (1, true); } else if (m_name == "aastep") { // all but the 5-arg version take derivs of edge param argtakesderivs (1, nargs<5); // aastep(f,f) and aastep(f,f,str) take derivs of s param if (nargs == 2 || list_nth(args(),2)->typespec().is_string()) argtakesderivs (2, true); } else if (m_name == "bump" || m_name == "displace") { // FIXME -- come back to this } else if (m_name == "calculatenormal") { argtakesderivs (1, true); } else if (m_name == "Dx" || m_name == "Dy") { argtakesderivs (1, true); } else if (m_name == "texture") { if (nargs == 3 || list_nth(args(),3)->typespec().is_string()) { argtakesderivs (2, true); argtakesderivs (3, true); } } else if (m_name == "texture3d") { if (nargs == 2 || list_nth(args(),2)->typespec().is_string()) { argtakesderivs (2, true); } } else if (m_name == "environment") { if (nargs == 2 || list_nth(args(),2)->typespec().is_string()) { argtakesderivs (2, true); } } else if (m_name == "trace") { argtakesderivs (1, true); argtakesderivs (2, true); } else { ASSERT (0 && "Missed a takes_derivs case!"); } } }
ikptr ikrt_process(ikptr rvec, ikptr env, ikptr cmd, ikptr argv /*, ikpcb* pcb */){ int infds[2]; int outfds[2]; int errfds[2]; int search_p = ref(rvec, off_vector_data+0*wordsize) != false_object; int stdin_fd = unfix(ref(rvec, off_vector_data+1*wordsize)); int stdout_fd = unfix(ref(rvec, off_vector_data+2*wordsize)); int stderr_fd = unfix(ref(rvec, off_vector_data+3*wordsize)); if(stdin_fd < 0 && pipe(infds)) return ik_errno_to_code(); if(stdout_fd < 0 && pipe(outfds)) return ik_errno_to_code(); if(stderr_fd < 0 && pipe(errfds)) return ik_errno_to_code(); pid_t pid = fork(); if(pid == 0){ /* child */ if (stdin_fd < 0){ if(close(infds[1])) exit(1); stdin_fd = infds[0]; } if (stdout_fd < 0){ if(close(outfds[0])) exit(1); stdout_fd = outfds[1]; } if (stderr_fd < 0){ if(close(errfds[0])) exit(1); stderr_fd = errfds[1]; } if (stdin_fd != 0){ if(close(0)) exit(1); if(dup(stdin_fd) == -1) exit(1); } if (stdout_fd != 1){ if(close(1)) exit(1); if(dup(stdout_fd) == -1) exit(1); } if (stderr_fd != 2){ if(close(2)) exit(2); if(dup(stderr_fd) == -1) exit(1); } char *cmd_str = (char*)(long)(cmd+off_bytevector_data); char **env_strs = env == false_object ? 0 : list_to_vec(env); char **argv_strs = list_to_vec(argv); if (env_strs && search_p) execvpe_(cmd_str, argv_strs, env_strs); else if (env_strs) execve(cmd_str, argv_strs, env_strs); else if (search_p) execvp(cmd_str, argv_strs); else execv(cmd_str, argv_strs); fprintf(stderr, "failed to exec %s: %s\n", (char*)(long)(cmd+off_bytevector_data), strerror(errno)); exit(-1); } else if(pid > 0){ /* parent */ ref(rvec,off_vector_data+0*wordsize) = fix(pid); if (stdin_fd < 0) { close(infds[0]); /* ignore errors */ ref(rvec,off_vector_data+1*wordsize) = fix(infds[1]); } if (stdout_fd < 0) { close(outfds[1]); ref(rvec,off_vector_data+2*wordsize) = fix(outfds[0]); } if (stderr_fd < 0) { close(errfds[1]); ref(rvec,off_vector_data+3*wordsize) = fix(errfds[0]); } return rvec; } else { return ik_errno_to_code(); } }