コード例 #1
0
ファイル: erlexec.c プロジェクト: AugustoFernandes/otp
static void add_epmd_port(void)
{
    char* port = get_env("ERL_EPMD_PORT");
    if (port != NULL) {
	add_args("-epmd_port", port, NULL);	
    }
}
コード例 #2
0
static gboolean
validate_icon_file (GFile *file, GError **error)
{
  g_autoptr(GPtrArray) args = NULL;
  const char *name;
  int status;
  g_autofree char *err = NULL;
  const char *validate_icon = LIBEXECDIR "/flatpak-validate-icon";

  name = flatpak_file_get_path_cached (file);

  if (g_getenv ("FLATPAK_VALIDATE_ICON"))
    validate_icon = g_getenv ("FLATPAK_VALIDATE_ICON");

  args = g_ptr_array_new_with_free_func (g_free);

#ifndef DISABLE_SANDBOXED_TRIGGERS
  if (!opt_disable_sandbox)
    add_args (args, validate_icon, "--sandbox", "512", "512", name, NULL);
  else
#endif
    add_args (args, validate_icon, "512", "512", name, NULL);

  g_ptr_array_add (args, NULL);

  if (!g_spawn_sync (NULL, (char **) args->pdata, NULL, 0, NULL, NULL, NULL, &err, &status, error))
    {
      g_debug ("Icon validation: %s", (*error)->message);
      return FALSE;
    }

  if (!g_spawn_check_exit_status (status, NULL))
    {
      g_debug ("Icon validation: %s", err);
      return flatpak_fail (error, "%s is not a valid icon: %s", name, err);
    }

  return TRUE;
}
コード例 #3
0
ファイル: os.c プロジェクト: dongzengwu/u-boot-stm32f4
int os_jump_to_image(const void *dest, int size)
{
	struct sandbox_state *state = state_get_current();
	char fname[30], mem_fname[30];
	int fd, err;
	const char *extra_args[5];
	char **argv = state->argv;
#ifdef DEBUG
	int argc, i;
#endif

	err = make_exec(fname, dest, size);
	if (err)
		return err;

	strcpy(mem_fname, "/tmp/u-boot.mem.XXXXXX");
	fd = mkstemp(mem_fname);
	if (fd < 0)
		return -ENOENT;
	close(fd);
	err = os_write_ram_buf(mem_fname);
	if (err)
		return err;

	os_fd_restore();

	extra_args[0] = "-j";
	extra_args[1] = fname;
	extra_args[2] = "-m";
	extra_args[3] = mem_fname;
	extra_args[4] = "--rm_memory";
	err = add_args(&argv, extra_args,
		       sizeof(extra_args) / sizeof(extra_args[0]));
	if (err)
		return err;

#ifdef DEBUG
	for (i = 0; argv[i]; i++)
		printf("%d %s\n", i, argv[i]);
#endif

	if (state_uninit())
		os_exit(2);

	err = execv(fname, argv);
	free(argv);
	if (err)
		return err;

	return unlink(fname);
}
コード例 #4
0
ファイル: main.c プロジェクト: x86kernel/ini
ARGS *parseargs(int argc, char *argv[])
{
#define ARGUMENTS_N 2
#define add_args(s) AddNode(args, "args", s, strlen(s))
	int iargc, iopt;
	char *optstring = "ca";
	const struct option opt[ARGUMENTS_N] = {{"comment"}, {"printall"}};
	ARGS *args = xmalloc(sizeof(LINKEDLIST));

	if(argc < 3)
		return NULL;
	else {
		for(iargc = 1; iargc < argc - 1; iargc++) {
			switch(get_optlong(argv[iargc])) {
				case 0:
					if(strchr(optstring, argv[iargc][1]))
						add_args(opt[strchr(optstring, argv[iargc][1]) - optstring].fulloptstring);
					else return (ARGS *)-1;
					break;
				case 1:
					for(iopt = 0; iopt < ARGUMENTS_N; iopt++) {
						if(!strcmp(&argv[iargc][2], opt[iopt].fulloptstring)) {
							add_args(&argv[iargc][2]);
							break;
						}
					}
					if(iopt == ARGUMENTS_N)
						return (ARGS *)-1;
					break;
				case -1:
					return (ARGS *)-1;
			}
		}
	}
	return args;
}
コード例 #5
0
ファイル: erlexec.c プロジェクト: AugustoFernandes/otp
int main(int argc, char **argv)
#endif
{
    int haltAfterwards = 0;	/* If true, put 's erlang halt' at the end
				 * of the arguments. */
    int isdistributed = 0;
    int no_epmd = 0;
    int i;
    char* s;
    char *epmd_prog = NULL;
    char *malloc_lib;
    int process_args = 1;
    int print_args_exit = 0;
    int print_qouted_cmd_exit = 0;
    erts_cpu_info_t *cpuinfo = NULL;

#ifdef __WIN32__
    this_module_handle = module;
    run_werl = windowed;
    /* if we started this erl just to get a detached emulator, 
     * the arguments are already prepared for beam, so we skip
     * directly to start_emulator */
    s = get_env("ERL_CONSOLE_MODE");
    if (s != NULL && strcmp(s, "detached")==0) {
	free_env_val(s);
	s = get_env("ERL_EMULATOR_DLL");
	if (s != NULL) {
	    argv[0] = strsave(s);
	} else {
	    argv[0] = strsave(EMULATOR_EXECUTABLE);
	}
	ensure_EargsSz(argc + 1);
	memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *));
	Eargsp[argc] = NULL;
	emu = argv[0];
	start_emulator_program = strsave(argv[0]);
	goto skip_arg_massage;
    }   
    free_env_val(s);
#else
    int reset_cerl_detached = 0;

    s = get_env("CERL_DETACHED_PROG");
    if (s && strcmp(s, "") != 0) {
	emu = s;
	start_detached = 1;
	reset_cerl_detached = 1;
	ensure_EargsSz(argc + 1);
	memcpy((void *) Eargsp, (void *) argv, argc * sizeof(char *));
	Eargsp[argc] = emu;
	Eargsp[argc] = NULL;
	goto skip_arg_massage;
    }
    free_env_val(s);
#endif

    initial_argv_massage(&argc, &argv); /* Merge with env; expand -args_file */

    i = 1;
#ifdef __WIN32__
    /* Not used? /rickard */
    if ((argc > 2) && (strcmp(argv[i], "-regkey") == 0)) {
	key_val_name = strsave(argv[i+1]);
	i = 3;
    }
#endif		

    get_parameters(argc, argv);
    
    /*
     * Construct the path of the executable.
     */
    cpuinfo = erts_cpu_info_create();
    /* '-smp auto' is default */ 
#ifdef ERTS_HAVE_SMP_EMU
    if (erts_get_cpu_configured(cpuinfo) > 1)
	emu_type |= EMU_TYPE_SMP;
#endif

#if defined(__WIN32__) && defined(WIN32_ALWAYS_DEBUG)
    emu_type_passed |= EMU_TYPE_DEBUG;
    emu_type |= EMU_TYPE_DEBUG;
#endif

    /* We need to do this before the ordinary processing. */
    malloc_lib = get_env("ERL_MALLOC_LIB");
    while (i < argc) {
	if (argv[i][0] == '+') {
	    if (argv[i][1] == 'M' && argv[i][2] == 'Y' && argv[i][3] == 'm') {
		if (argv[i][4] == '\0') {
		    if (++i < argc)
			malloc_lib = argv[i];
		    else
			usage("+MYm");
		}
		else
		    malloc_lib = &argv[i][4];
	    }
	}
	else if (argv[i][0] == '-') {
	    if (strcmp(argv[i], "-smp") == 0) {
		if (i + 1 >= argc)
		    goto smp;

		if (strcmp(argv[i+1], "auto") == 0) {
		    i++;
		smp_auto:
		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    if (erts_get_cpu_configured(cpuinfo) > 1)
			emu_type |= EMU_TYPE_SMP;
		    else
#endif
			emu_type &= ~EMU_TYPE_SMP;
		}
		else if (strcmp(argv[i+1], "enable") == 0) {
		    i++;
		smp_enable:
		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    emu_type |= EMU_TYPE_SMP;
#else
		    usage_notsup("-smp enable");
#endif
		}
		else if (strcmp(argv[i+1], "disable") == 0) {
		    i++;
		smp_disable:
		    emu_type_passed |= EMU_TYPE_SMP;
		    emu_type &= ~EMU_TYPE_SMP;
		}
		else {
		smp:

		    emu_type_passed |= EMU_TYPE_SMP;
#ifdef ERTS_HAVE_SMP_EMU
		    emu_type |= EMU_TYPE_SMP;
#else
		    usage_notsup("-smp");
#endif
		}
	    } else if (strcmp(argv[i], "-smpenable") == 0) {
		goto smp_enable;
	    } else if (strcmp(argv[i], "-smpauto") == 0) {
		goto smp_auto;
	    } else if (strcmp(argv[i], "-smpdisable") == 0) {
		goto smp_disable;
#ifdef __WIN32__
	    } else if (strcmp(argv[i], "-debug") == 0) {
		emu_type_passed |= EMU_TYPE_DEBUG;
		emu_type |= EMU_TYPE_DEBUG;
#endif
	    } else if (strcmp(argv[i], "-hybrid") == 0) {
		emu_type_passed |= EMU_TYPE_HYBRID;
#ifdef ERTS_HAVE_HYBRID_EMU
		emu_type |= EMU_TYPE_HYBRID;
#else
		usage_notsup("-hybrid");
#endif
	    } else if (strcmp(argv[i], "-extra") == 0) {
		break;
	    }
	}
	i++;
    }

    erts_cpu_info_destroy(cpuinfo);
    cpuinfo = NULL;

    if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
	/*
	 * We have a conflict. Only using explicitly passed arguments
	 * may solve it...
	 */
	emu_type &= emu_type_passed;
	if ((emu_type & EMU_TYPE_HYBRID) && (emu_type & EMU_TYPE_SMP)) {
	    usage_msg("Hybrid heap emulator with SMP support selected. The "
		      "combination hybrid heap and SMP support is currently "
		      "not supported.");
	}
    }

    if (malloc_lib) {
	if (strcmp(malloc_lib, "libc") != 0)
	    usage("+MYm");
    }
    emu = add_extra_suffixes(emu, emu_type);
    sprintf(tmpStr, "%s" DIRSEP "%s" BINARY_EXT, bindir, emu);
    emu = strsave(tmpStr);

    add_Eargs(emu);		/* Will be argv[0] -- necessary! */

    /*
     * Add the bindir to the path (unless it is there already).
     */

    s = get_env("PATH");
    if (!s) {
	sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin", bindir, rootdir);
    } else if (strstr(s, bindir) == NULL) {
	sprintf(tmpStr, "%s" PATHSEP "%s" DIRSEP "bin" PATHSEP "%s", bindir, 
		rootdir, s);
    } else {
	sprintf(tmpStr, "%s", s);
    }
    free_env_val(s);
    set_env("PATH", tmpStr);
    
    i = 1;

#ifdef __WIN32__
#define ADD_BOOT_CONFIG					\
    if (boot_script)					\
	add_args("-boot", boot_script, NULL);		\
    if (config_script)					\
	add_args("-config", config_script, NULL);
#else
#define ADD_BOOT_CONFIG
#endif

    get_home();
    add_args("-home", home, NULL);

    add_epmd_port();

    add_arg("--");

    while (i < argc) {
	if (!process_args) {	/* Copy arguments after '-extra' */
	    add_arg(argv[i]);
	    i++;
	} else {
	    switch (argv[i][0]) {
	      case '-':
		switch (argv[i][1]) {
#ifdef __WIN32__
		case 'b':
		    if (strcmp(argv[i], "-boot") == 0) {
			if (boot_script)
			    error("Conflicting -start_erl and -boot options");
			if (i+1 >= argc)
			    usage("-boot");
			boot_script = strsave(argv[i+1]);
			i++;
		    }
		    else {
			add_arg(argv[i]);
		    }
		    break;
#endif
		case 'c':
		    if (strcmp(argv[i], "-compile") == 0) {
			/*
			 * Note that the shell script erl.exec does an recursive call
			 * on itself here.  We'll avoid doing that.
			 */
			add_args("-noshell", "-noinput", "-s", "c", "lc_batch",
				 NULL);
			add_Eargs("-B");
			haltAfterwards = 0;
		    }
#ifdef __WIN32__
		    else if (strcmp(argv[i], "-config") == 0){
			if (config_script)
			    error("Conflicting -start_erl and -config options");
			if (i+1 >= argc)
			    usage("-config");
			config_script = strsave(argv[i+1]);
			i++;
		    }
#endif
		    else {
			add_arg(argv[i]);
		    }
		    break;

		  case 'd':
		    if (strcmp(argv[i], "-detached") != 0) {
			add_arg(argv[i]);
		    } else {
			start_detached = 1;
			add_args("-noshell", "-noinput", NULL);
		    }
		    break;

		  case 'i':
		    if (strcmp(argv[i], "-instr") == 0) {
			add_Eargs("-Mim");
			add_Eargs("true");
		    }
		    else
			add_arg(argv[i]);
		    break;

		  case 'e':
		    if (strcmp(argv[i], "-extra") == 0) {
			process_args = 0;
			ADD_BOOT_CONFIG;
			add_arg(argv[i]);
		    } else if (strcmp(argv[i], "-emu_args") == 0) { /* -emu_args */
			verbose = 1;
		    } else if (strcmp(argv[i], "-emu_args_exit") == 0) {
			print_args_exit = 1;
		    } else if (strcmp(argv[i], "-emu_qouted_cmd_exit") == 0) {
			print_qouted_cmd_exit = 1;
		    } else if (strcmp(argv[i], "-env") == 0) { /* -env VARNAME VARVALUE */
			if (i+2 >= argc)
			    usage("-env");
			set_env(argv[i+1], argv[i+2]);
			i += 2;
		    } else if (strcmp(argv[i], "-epmd") == 0) { 
			if (i+1 >= argc)
			    usage("-epmd");
			epmd_prog = argv[i+1];
			++i;
		    } else {
			add_arg(argv[i]);
		    }
		    break;
		  case 'k':
		    if (strcmp(argv[i], "-keep_window") == 0) {
			keep_window = 1;
		    } else
			add_arg(argv[i]);
		    break;

		  case 'm':
		    /*
		     * Note that the shell script erl.exec does an recursive call
		     * on itself here.  We'll avoid doing that.
		     */
		    if (strcmp(argv[i], "-make") == 0) {
			add_args("-noshell", "-noinput", "-s", "make", "all", NULL);
			add_Eargs("-B");
			haltAfterwards = 1;
			i = argc; /* Skip rest of command line */
		    } else if (strcmp(argv[i], "-man") == 0) {
#if defined(__WIN32__)
			error("-man not supported on Windows");
#else
			argv[i] = "man";
			sprintf(tmpStr, "%s/man", rootdir);
			set_env("MANPATH", tmpStr);
			execvp("man", argv+i);
			error("Could not execute the 'man' command.");
#endif
		    } else
			add_arg(argv[i]);
		    break;

		  case 'n':
		    if (strcmp(argv[i], "-name") == 0) { /* -name NAME */
			if (i+1 >= argc)
			    usage("-name");
		    
			/*
			 * Note: Cannot use add_args() here, due to non-defined
			 * evaluation order.
			 */

			add_arg(argv[i]);
			add_arg(argv[i+1]);
			isdistributed = 1;
			i++;
		    } else if (strcmp(argv[i], "-noinput") == 0) {
			add_args("-noshell", "-noinput", NULL);
		    } else if (strcmp(argv[i], "-nohup") == 0) {
			add_arg("-nohup");
			nohup = 1;
		    } else if (strcmp(argv[i], "-no_epmd") == 0) {
			add_arg("-no_epmd");
			no_epmd = 1;
		    } else {
			add_arg(argv[i]);
		    }
		    break;

		  case 's':	/* -sname NAME */
		    if (strcmp(argv[i], "-sname") == 0) {
			if (i+1 >= argc)
			    usage("-sname");
			add_arg(argv[i]);
			add_arg(argv[i+1]);
			isdistributed = 1;
			i++;
		    }
#ifdef __WIN32__
		    else if (strcmp(argv[i], "-service_event") == 0) {
			add_arg(argv[i]);
			add_arg(argv[i+1]);
			i++;
		    }		    
		    else if (strcmp(argv[i], "-start_erl") == 0) {
			if (i+1 < argc && argv[i+1][0] != '-') {
			    get_start_erl_data(argv[i+1]);
			    i++;
			} else
			    get_start_erl_data((char *) NULL);
		    }
#endif
		    else
			add_arg(argv[i]);
		
		    break;
	
		  case 'v':	/* -version */
		    if (strcmp(argv[i], "-version") == 0) {
			add_Eargs("-V");
		    } else {
			add_arg(argv[i]);
		    }
		    break;

		  default:
		    add_arg(argv[i]);
		    break;
		} /* switch(argv[i][1] */
		break;

	      case '+':
		switch (argv[i][1]) {
		  case '#':
		  case 'a':
		  case 'A':
		  case 'b':
		  case 'h':
		  case 'i':
		  case 'P':
		  case 'S':
		  case 'T':
		  case 'R':
		  case 'W':
		  case 'K':
		      if (argv[i][2] != '\0')
			  goto the_default;
		      if (i+1 >= argc)
			  usage(argv[i]);
		      argv[i][0] = '-';
		      add_Eargs(argv[i]);
		      add_Eargs(argv[i+1]);
		      i++;
		      break;
		  case 'B':
		      argv[i][0] = '-';
		      if (argv[i][2] != '\0') {
			  if ((argv[i][2] != 'i') &&
			      (argv[i][2] != 'c') &&
			      (argv[i][2] != 'd')) { 
			  usage(argv[i]);
			} else {
			  add_Eargs(argv[i]);
			  break;
			}
		      }
		      if (i+1 < argc) {
			if ((argv[i+1][0] != '-') &&
			    (argv[i+1][0] != '+')) {
			  if (argv[i+1][0] == 'i') {
			    add_Eargs(argv[i]);
			    add_Eargs(argv[i+1]);
			    i++;
			    break;
			  } else {
			    usage(argv[i]);
			  }
			}
		      }
		      add_Eargs(argv[i]);
		      break;
		  case 'M': {
		      int x;
		      for (x = 0; plusM_au_allocs[x]; x++)
			  if (plusM_au_allocs[x] == argv[i][2])
			      break;
		      if ((plusM_au_allocs[x]
			   && is_one_of_strings(&argv[i][3],
						plusM_au_alloc_switches))
			  || is_one_of_strings(&argv[i][2],
					       plusM_other_switches)) {
			  if (i+1 >= argc
			      || argv[i+1][0] == '-'
			      || argv[i+1][0] == '+')
			      usage(argv[i]);
			  argv[i][0] = '-';
			  add_Eargs(argv[i]);
			  add_Eargs(argv[i+1]);
			  i++;
		      }
		      else
			  goto the_default;
		      break;
		  }
		  case 's':
		      if (!is_one_of_strings(&argv[i][2],
					     pluss_val_switches))
			  goto the_default;
		      else {
			  if (i+1 >= argc
			      || argv[i+1][0] == '-'
			      || argv[i+1][0] == '+')
			      usage(argv[i]);
			  argv[i][0] = '-';
			  add_Eargs(argv[i]);
			  add_Eargs(argv[i+1]);
			  i++;
		      }
		      break;
		  default:
		  the_default:
		    argv[i][0] = '-'; /* Change +option to -option. */
		    add_Eargs(argv[i]);
		}
		break;
      
	      default:
		add_arg(argv[i]);
	    } /* switch(argv[i][0] */
	    i++;
	}
    }

    if (process_args) {
	ADD_BOOT_CONFIG;
    }
#undef ADD_BOOT_CONFIG

    /* Doesn't conflict with -extra, since -make skips all the rest of
       the arguments. */
    if (haltAfterwards) {
	add_args("-s", "erlang", "halt", NULL);
    }
    
    if (isdistributed && !no_epmd)
	start_epmd(epmd_prog);

#if (! defined(__WIN32__)) && defined(DEBUG)
    if (start_detached) {
	/* Start the emulator within an xterm.
	 * Move up all arguments and insert
	 * "xterm -e " first.
	 * The path must be searched for this 
	 * to work, i.e execvp() must be used. 
	 */
	ensure_EargsSz(EargsCnt+2);
	for (i = EargsCnt; i > 0; i--)
	    Eargsp[i+1] = Eargsp[i-1]; /* Two args to insert */
	EargsCnt += 2; /* Two args to insert */
	Eargsp[0] = emu = "xterm";
	Eargsp[1] = "-e";
    }    
#endif
    
    add_Eargs("--");
    add_Eargs("-root");
    add_Eargs(rootdir);
    add_Eargs("-progname");
    add_Eargs(progname);
    add_Eargs("--");
    ensure_EargsSz(EargsCnt + argsCnt + 1);
    for (i = 0; i < argsCnt; i++)
	Eargsp[EargsCnt++] = argsp[i];
    Eargsp[EargsCnt] = NULL;
    
    if (print_qouted_cmd_exit) {
	printf("\"%s\" ", emu);
	for (i = 1; i < EargsCnt; i++)
	    printf("\"%s\" ", Eargsp[i]);
	printf("\n");
	exit(0);
    }

    if (print_args_exit) {
	for (i = 1; i < EargsCnt; i++)
	    printf("%s ", Eargsp[i]);
	printf("\n");
	exit(0);
    }

    if (verbose) {
	printf("Executing: %s", emu);
	for (i = 0; i < EargsCnt; i++)
	    printf(" %s", Eargsp[i]);
	printf("\n\n");
    }

#ifdef __WIN32__

    if (EargsSz != EargsCnt + 1)
	Eargsp = (char **) erealloc((void *) Eargsp, (EargsCnt + 1) * 
				    sizeof(char *));
    efree((void *) argsp);

 skip_arg_massage:
    /*DebugBreak();*/

    if (run_werl) {
	if (start_detached) {
	    char *p;
	    /* transform werl to erl */
	    p = start_emulator_program+strlen(start_emulator_program);
	    while (--p >= start_emulator_program && *p != '/' && *p != '\\' &&
		   *p != 'W' && *p != 'w')
		;
	    if (p >= start_emulator_program && (*p == 'W' || *p == 'w') &&
		(p[1] == 'E' || p[1] == 'e') && (p[2] == 'R' || p[2] == 'r') &&
		(p[3] == 'L' || p[3] == 'l')) {
		memmove(p,p+1,strlen(p));
	    }
	}
      return start_win_emulator(emu, start_emulator_program, Eargsp, start_detached);
    } else {
      return start_emulator(emu, start_emulator_program, Eargsp, start_detached);
    }

#else

 skip_arg_massage:
    if (start_detached) {
	int status = fork();
	if (status != 0)	/* Parent */
	    return 0;

	if (reset_cerl_detached)
	    putenv("CERL_DETACHED_PROG=");

	/* Detach from controlling terminal */
#ifdef HAVE_SETSID
	setsid();
#elif defined(TIOCNOTTY)
	{
	  int fd = open("/dev/tty", O_RDWR);
	  if (fd >= 0) {
	    ioctl(fd, TIOCNOTTY, NULL);
	    close(fd);
	  }
	}
#endif

	status = fork();
	if (status != 0)	/* Parent */
	    return 0;

	/*
	 * Grandchild.
	 */
	close(0);
	open("/dev/null", O_RDONLY);
	close(1);
	open("/dev/null", O_WRONLY);
	close(2);
	open("/dev/null", O_WRONLY);
#ifdef DEBUG
	execvp(emu, Eargsp); /* "xterm ..." needs to search the path */
#endif
    } 
#ifdef DEBUG
    else
#endif
    {
	execv(emu, Eargsp);
    }
    error("Error %d executing \'%s\'.", errno, emu);
    return 1;
#endif
}
コード例 #6
0
ファイル: validate.c プロジェクト: invisibleboy/mycompiler
/*! \brief Validates a function call.
 *
 * \param e
 *  the Expr to inspect.
 * \param data
 *  a pointer to a validate_arg struct.
 *
 * Validates the arguments to a function call against the called
 * function's param types.  If a parameter is of a multi type union,
 * the correct field is selected.  If the call has too many or too few
 * arguments, this is corrected
 */
static void
validate_call (Expr e, void *data)
{
    validate_arg *arg = (validate_arg *)data;
    Expr callee_expr, cur_arg, next_arg;
    FuncDcl func;
    Key func_scope_key;
    Type func_type, param_type, cur_arg_type;
    Param param;

    if (e && P_GetExprOpcode (e) == OP_call)
    {
        /* Get the callee function's type. */
        callee_expr = P_GetExprOperands (e);
        func_type = PST_ExprType (arg->ip_table, P_GetExprOperands (e));

        /* We can only validate direct calls of defined functions. */
        if (P_IsIndirectFunctionCall (e))
        {
            func_scope_key = PST_GetScopeFromEntryKey (arg->ip_table, func_type);

            /* If we have an indirect call with unspecified parameters, we
             * can't do anything more. */
            if (PST_GetTypeParam (arg->ip_table, func_type) == NULL)
                return;
        }
        else if (P_IsDirectFunctionCall (e))
        {
            func = PST_GetFuncDclEntry (arg->ip_table,
                                        P_GetExprVarKey (callee_expr));

            if (!P_TstFuncDclQualifier (func, VQ_DEFINED) || \
                    P_TstFuncDclQualifier (func, VQ_APP_ELLIPSIS))
                goto done;

            func_scope_key = \
                             PST_GetScopeFromEntryKey (arg->ip_table,
                                     P_GetExprVarKey (callee_expr));
        }

        if (!PST_IsFunctionType (arg->ip_table, func_type))
            P_punt ("validate.c:validate_call:%d e does not result in a\n"
                    "function type (%d, %d)", __LINE__, func_type.file,
                    func_type.sym);

        /* Loop through the call arguments and the function parameters to
         * determine if we need to do anything. */
        cur_arg = P_GetExprSibling (callee_expr);
        param = PST_GetTypeParam (arg->ip_table, func_type);
        while (cur_arg && param)
        {
            bool arg_is_multi, arg_is_pointer, param_is_multi, param_is_pointer;

            next_arg = P_GetExprNext (cur_arg);

            param_type = P_GetParamKey (param);
            cur_arg_type = PST_ExprType (arg->ip_table, cur_arg);

            /* If the current param is a vararg, the call does not require
             * repair. */
            if (PST_IsVarargType (arg->ip_table, param_type))
                goto done;

            arg_is_multi = is_multi_type (arg->ip_table, cur_arg_type);
            arg_is_pointer = is_pointer_type (arg->ip_table, cur_arg_type);
            param_is_multi = is_multi_type (arg->ip_table, param_type);
            param_is_pointer = is_pointer_type (arg->ip_table, param_type);

            if (param_is_pointer && arg_is_pointer)
            {
                /* Build (t.field1 = cur_arg, t).field2 */
                TypeDcl td = PST_GetTypeTypeDcl (arg->ip_table, param_type);
                Type multi_type = Plink_GetTypeDclMultiType (td);

                cur_arg = make_struct_pointer_multi (arg->ip_table, multi_type,
                                                     cur_arg);
                cur_arg = make_dot (arg->ip_table, cur_arg, multi_type,
                                    func_scope_key);

                arg->must_flatten = TRUE;
            }
            else if (param_is_pointer && arg_is_multi)
            {
                /* Build (arg.field). */
                cur_arg = make_dot (arg->ip_table, cur_arg, cur_arg_type,
                                    func_scope_key);

                arg->must_flatten = TRUE;
            }
            else if (param_is_multi && !arg_is_multi)
            {
                /* Build (t.field = cur_arg, t) */
                make_struct_pointer_multi (arg->ip_table, param_type, cur_arg);

                arg->must_flatten = TRUE;
            }
            else
            {
                /* If the argument type doesn't match the parameter type, cast
                 * it. */
                if (PST_IsPointerType (arg->ip_table, param_type) && \
                        PST_IsIntegralType (arg->ip_table, cur_arg_type))
                {
                    Key scope_key = PST_GetExprScope (arg->ip_table, cur_arg);
                    Expr cast = PST_ScopeNewExprWithOpcode (arg->ip_table,
                                                            scope_key, OP_cast);

                    P_ExprSwap (&cur_arg, &cast);
                    P_AppendExprOperands (cast, cur_arg);
                    PST_SetExprType (arg->ip_table, cast, param_type);
                }
            }

            cur_arg = next_arg;
            param = P_GetParamNext (param);
        }

        if (cur_arg || param)
        {
            if (cur_arg)
            {
                /* If there are too many arguments, we need to remove extra ones
                 * from the end. */
                e->pragma = \
                            P_AppendPragmaNext (e->pragma,
                                                P_NewPragmaWithSpecExpr ("PLV_REMOVE",
                                                        NULL));
                remove_args (arg->ip_table, e, cur_arg);

                arg->must_flatten = TRUE;
            }
            else if (param)
            {
                /* If there are too few arguments, we need to add extras to pad
                 * the call. */
                e->pragma = \
                            P_AppendPragmaNext (e->pragma,
                                                P_NewPragmaWithSpecExpr ("PLV_ADD", NULL));
                add_args (arg->ip_table, e, param);
            }
        }
    }

done:
    return;
}