static int execute_csharp_using_sscli (const char *assembly_path, const char * const *libdirs, unsigned int libdirs_count, const char * const *args, unsigned int nargs, bool verbose, bool quiet, execute_fn *executer, void *private_data) { static bool clix_tested; static bool clix_present; if (!clix_tested) { /* Test for presence of clix: "clix >/dev/null 2>/dev/null ; test $? = 1" */ char *argv[2]; int exitstatus; argv[0] = "clix"; argv[1] = NULL; exitstatus = execute ("clix", "clix", argv, false, false, true, true, true, false, NULL); clix_present = (exitstatus == 0 || exitstatus == 1); clix_tested = true; } if (clix_present) { char *old_clixpath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; bool err; /* Set clix' PATH variable. */ old_clixpath = set_clixpath (libdirs, libdirs_count, false, verbose); argv[0] = "clix"; argv[1] = (char *) assembly_path; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("clix", "clix", argv, private_data); /* Reset clix' PATH variable. */ reset_clixpath (old_clixpath); freea (argv); return err; } else return -1; }
static int message_list_hash_insert_entry (hash_table *htable, message_ty *mp) { char *alloced_key; const char *key; size_t keylen; int found; if (mp->msgctxt != NULL) { /* Concatenate mp->msgctxt and mp->msgid, to form the hash table key. */ size_t msgctxt_len = strlen (mp->msgctxt); size_t msgid_len = strlen (mp->msgid); keylen = msgctxt_len + 1 + msgid_len + 1; alloced_key = (char *) xmalloca (keylen); memcpy (alloced_key, mp->msgctxt, msgctxt_len); alloced_key[msgctxt_len] = MSGCTXT_SEPARATOR; memcpy (alloced_key + msgctxt_len + 1, mp->msgid, msgid_len + 1); key = alloced_key; } else { alloced_key = NULL; key = mp->msgid; keylen = strlen (mp->msgid) + 1; } found = (hash_insert_entry (htable, key, keylen, mp) == NULL); if (mp->msgctxt != NULL) freea (alloced_key); return found; }
message_ty * message_list_search (message_list_ty *mlp, const char *msgctxt, const char *msgid) { if (mlp->use_hashtable) { char *alloced_key; const char *key; size_t keylen; if (msgctxt != NULL) { /* Concatenate the msgctxt and msgid, to form the hash table key. */ size_t msgctxt_len = strlen (msgctxt); size_t msgid_len = strlen (msgid); keylen = msgctxt_len + 1 + msgid_len + 1; alloced_key = (char *) xmalloca (keylen); memcpy (alloced_key, msgctxt, msgctxt_len); alloced_key[msgctxt_len] = MSGCTXT_SEPARATOR; memcpy (alloced_key + msgctxt_len + 1, msgid, msgid_len + 1); key = alloced_key; } else { alloced_key = NULL; key = msgid; keylen = strlen (msgid) + 1; } { void *htable_value; int found = !hash_find_entry (&mlp->htable, key, keylen, &htable_value); if (msgctxt != NULL) freea (alloced_key); if (found) return (message_ty *) htable_value; else return NULL; } } else { size_t j; for (j = 0; j < mlp->nitems; ++j) { message_ty *mp; mp = mlp->item[j]; if ((msgctxt != NULL ? mp->msgctxt != NULL && strcmp (msgctxt, mp->msgctxt) == 0 : mp->msgctxt == NULL) && strcmp (msgid, mp->msgid) == 0) return mp; } return NULL; } }
/* File open routine that understands `-' as stdin/stdout and `|cmd' as a pipe to command `cmd'. Returns resultant FILE on success, NULL on failure. If NULL is returned then errno is set to a sensible value. */ FILE * fn_open (const char *fn, const char *mode) { assert (mode[0] == 'r' || mode[0] == 'w' || mode[0] == 'a'); if (mode[0] == 'r') { if (!strcmp (fn, "stdin") || !strcmp (fn, "-")) return stdin; } else { if (!strcmp (fn, "stdout") || !strcmp (fn, "-")) return stdout; if (!strcmp (fn, "stderr")) return stderr; } #if HAVE_POPEN if (fn[0] == '|') { if (settings_get_safer_mode ()) return safety_violation (fn); return popen (&fn[1], mode[0] == 'r' ? "r" : "w"); } else if (*fn && fn[strlen (fn) - 1] == '|') { char *s; FILE *f; if (settings_get_safer_mode ()) return safety_violation (fn); s = xmalloca (strlen (fn)); memcpy (s, fn, strlen (fn) - 1); s[strlen (fn) - 1] = 0; f = popen (s, mode[0] == 'r' ? "r" : "w"); freea (s); return f; } else #endif return fopen (fn, mode); }
void po_lex_charset_set (const char *header_entry, const char *filename) { /* Verify the validity of CHARSET. It is necessary 1. for the correct treatment of multibyte characters containing 0x5C bytes in the PO lexer, 2. so that at run time, gettext() can call iconv() to convert msgstr. */ const char *charsetstr = c_strstr (header_entry, "charset="); if (charsetstr != NULL) { size_t len; char *charset; const char *canon_charset; charsetstr += strlen ("charset="); len = strcspn (charsetstr, " \t\n"); charset = (char *) xmalloca (len + 1); memcpy (charset, charsetstr, len); charset[len] = '\0'; canon_charset = po_charset_canonicalize (charset); if (canon_charset == NULL) { /* Don't warn for POT files, because POT files usually contain only ASCII msgids. */ size_t filenamelen = strlen (filename); if (!(filenamelen >= 4 && memcmp (filename + filenamelen - 4, ".pot", 4) == 0 && strcmp (charset, "CHARSET") == 0)) { char *warning_message = xasprintf (_("\ Charset \"%s\" is not a portable encoding name.\n\ Message conversion to user's charset might not work.\n"), charset); po_xerror (PO_SEVERITY_WARNING, NULL, filename, (size_t)(-1), (size_t)(-1), true, warning_message); free (warning_message); }
static int compile_csharp_using_pnet (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool cscc_tested; static bool cscc_present; if (!cscc_tested) { /* Test for presence of cscc: "cscc --version >/dev/null 2>/dev/null" */ char *argv[3]; int exitstatus; argv[0] = "cscc"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("cscc", "cscc", argv, false, false, true, true, true, false, NULL); cscc_present = (exitstatus == 0); cscc_tested = true; } if (cscc_present) { unsigned int argc; char **argv; char **argp; int exitstatus; unsigned int i; argc = 1 + (output_is_library ? 1 : 0) + 2 + 2 * libdirs_count + 2 * libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "cscc"; if (output_is_library) *argp++ = "-shared"; *argp++ = "-o"; *argp++ = (char *) output_file; for (i = 0; i < libdirs_count; i++) { *argp++ = "-L"; *argp++ = (char *) libdirs[i]; } for (i = 0; i < libraries_count; i++) { *argp++ = "-l"; *argp++ = (char *) libraries[i]; } if (optimize) *argp++ = "-O"; if (debug) *argp++ = "-g"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 10 && memcmp (source_file + strlen (source_file) - 10, ".resources", 10) == 0) { char *option = (char *) xmalloca (12 + strlen (source_file) + 1); memcpy (option, "-fresources=", 12); strcpy (option + 12, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } exitstatus = execute ("cscc", "cscc", argv, false, false, false, false, true, true, NULL); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freea (argv[argc - sources_count + i]); freea (argv); return (exitstatus != 0); } else return -1; }
static int compile_csharp_using_sscli (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool csc_tested; static bool csc_present; if (!csc_tested) { /* Test for presence of csc: "csc -help >/dev/null 2>/dev/null \ && ! { csc -help 2>/dev/null | grep -i chicken > /dev/null; }" */ char *argv[3]; pid_t child; int fd[1]; int exitstatus; argv[0] = "csc"; argv[1] = "-help"; argv[2] = NULL; child = create_pipe_in ("csc", "csc", argv, DEV_NULL, true, true, false, fd); csc_present = false; if (child != -1) { /* Read the subprocess output, and test whether it contains the string "chicken". */ char c[7]; size_t count = 0; csc_present = true; while (safe_read (fd[0], &c[count], 1) > 0) { if (c[count] >= 'A' && c[count] <= 'Z') c[count] += 'a' - 'A'; count++; if (count == 7) { if (memcmp (c, "chicken", 7) == 0) csc_present = false; c[0] = c[1]; c[1] = c[2]; c[2] = c[3]; c[3] = c[4]; c[4] = c[5]; c[5] = c[6]; count--; } } close (fd[0]); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "csc", false, true, true, false, NULL); if (exitstatus != 0) csc_present = false; } csc_tested = true; } if (csc_present) { unsigned int argc; char **argv; char **argp; int exitstatus; unsigned int i; argc = 1 + 1 + 1 + libdirs_count + libraries_count + (optimize ? 1 : 0) + (debug ? 1 : 0) + sources_count; argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "csc"; *argp++ = (char *) (output_is_library ? "-target:library" : "-target:exe"); { char *option = (char *) xmalloca (5 + strlen (output_file) + 1); memcpy (option, "-out:", 5); strcpy (option + 5, output_file); *argp++ = option; } for (i = 0; i < libdirs_count; i++) { char *option = (char *) xmalloca (5 + strlen (libdirs[i]) + 1); memcpy (option, "-lib:", 5); strcpy (option + 5, libdirs[i]); *argp++ = option; } for (i = 0; i < libraries_count; i++) { char *option = (char *) xmalloca (11 + strlen (libraries[i]) + 4 + 1); memcpy (option, "-reference:", 11); memcpy (option + 11, libraries[i], strlen (libraries[i])); strcpy (option + 11 + strlen (libraries[i]), ".dll"); *argp++ = option; } if (optimize) *argp++ = "-optimize+"; if (debug) *argp++ = "-debug+"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 10 && memcmp (source_file + strlen (source_file) - 10, ".resources", 10) == 0) { char *option = (char *) xmalloca (10 + strlen (source_file) + 1); memcpy (option, "-resource:", 10); strcpy (option + 10, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } exitstatus = execute ("csc", "csc", argv, false, false, false, false, true, true, NULL); for (i = 2; i < 3 + libdirs_count + libraries_count; i++) freea (argv[i]); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freea (argv[argc - sources_count + i]); freea (argv); return (exitstatus != 0); } else return -1; }
static int compile_csharp_using_mono (const char * const *sources, unsigned int sources_count, const char * const *libdirs, unsigned int libdirs_count, const char * const *libraries, unsigned int libraries_count, const char *output_file, bool output_is_library, bool optimize, bool debug, bool verbose) { static bool mcs_tested; static bool mcs_present; if (!mcs_tested) { /* Test for presence of mcs: "mcs --version >/dev/null 2>/dev/null" and (to exclude an unrelated 'mcs' program on QNX 6) "mcs --version 2>/dev/null | grep Mono >/dev/null" */ char *argv[3]; pid_t child; int fd[1]; int exitstatus; argv[0] = "mcs"; argv[1] = "--version"; argv[2] = NULL; child = create_pipe_in ("mcs", "mcs", argv, DEV_NULL, true, true, false, fd); mcs_present = false; if (child != -1) { /* Read the subprocess output, and test whether it contains the string "Mono". */ char c[4]; size_t count = 0; while (safe_read (fd[0], &c[count], 1) > 0) { count++; if (count == 4) { if (memcmp (c, "Mono", 4) == 0) mcs_present = true; c[0] = c[1]; c[1] = c[2]; c[2] = c[3]; count--; } } close (fd[0]); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "mcs", false, true, true, false, NULL); if (exitstatus != 0) mcs_present = false; } mcs_tested = true; } if (mcs_present) { unsigned int argc; char **argv; char **argp; pid_t child; int fd[1]; FILE *fp; char *line[2]; size_t linesize[2]; size_t linelen[2]; unsigned int l; int exitstatus; unsigned int i; argc = 1 + (output_is_library ? 1 : 0) + 1 + libdirs_count + libraries_count + (debug ? 1 : 0) + sources_count; argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "mcs"; if (output_is_library) *argp++ = "-target:library"; { char *option = (char *) xmalloca (5 + strlen (output_file) + 1); memcpy (option, "-out:", 5); strcpy (option + 5, output_file); *argp++ = option; } for (i = 0; i < libdirs_count; i++) { char *option = (char *) xmalloca (5 + strlen (libdirs[i]) + 1); memcpy (option, "-lib:", 5); strcpy (option + 5, libdirs[i]); *argp++ = option; } for (i = 0; i < libraries_count; i++) { char *option = (char *) xmalloca (11 + strlen (libraries[i]) + 4 + 1); memcpy (option, "-reference:", 11); memcpy (option + 11, libraries[i], strlen (libraries[i])); strcpy (option + 11 + strlen (libraries[i]), ".dll"); *argp++ = option; } if (debug) *argp++ = "-debug"; for (i = 0; i < sources_count; i++) { const char *source_file = sources[i]; if (strlen (source_file) >= 10 && memcmp (source_file + strlen (source_file) - 10, ".resources", 10) == 0) { char *option = (char *) xmalloca (10 + strlen (source_file) + 1); memcpy (option, "-resource:", 10); strcpy (option + 10, source_file); *argp++ = option; } else *argp++ = (char *) source_file; } *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } child = create_pipe_in ("mcs", "mcs", argv, NULL, false, true, true, fd); /* Read the subprocess output, copying it to stderr. Drop the last line if it starts with "Compilation succeeded". */ fp = fdopen (fd[0], "r"); if (fp == NULL) error (EXIT_FAILURE, errno, _("fdopen() failed")); line[0] = NULL; linesize[0] = 0; line[1] = NULL; linesize[1] = 0; l = 0; for (;;) { linelen[l] = getline (&line[l], &linesize[l], fp); if (linelen[l] == (size_t)(-1)) break; l = (l + 1) % 2; if (line[l] != NULL) fwrite (line[l], 1, linelen[l], stderr); } l = (l + 1) % 2; if (line[l] != NULL && !(linelen[l] >= 21 && memcmp (line[l], "Compilation succeeded", 21) == 0)) fwrite (line[l], 1, linelen[l], stderr); if (line[0] != NULL) free (line[0]); if (line[1] != NULL) free (line[1]); fclose (fp); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "mcs", false, false, true, true, NULL); for (i = 1 + (output_is_library ? 1 : 0); i < 1 + (output_is_library ? 1 : 0) + 1 + libdirs_count + libraries_count; i++) freea (argv[i]); for (i = 0; i < sources_count; i++) if (argv[argc - sources_count + i] != sources[i]) freea (argv[argc - sources_count + i]); freea (argv); return (exitstatus != 0); } else return -1; }
static int execute_csharp_using_pnet (const char *assembly_path, const char * const *libdirs, unsigned int libdirs_count, const char * const *args, unsigned int nargs, bool verbose, bool quiet, execute_fn *executer, void *private_data) { static bool ilrun_tested; static bool ilrun_present; if (!ilrun_tested) { /* Test for presence of ilrun: "ilrun --version >/dev/null 2>/dev/null" */ char *argv[3]; int exitstatus; argv[0] = "ilrun"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("ilrun", "ilrun", argv, false, false, true, true, true, false, NULL); ilrun_present = (exitstatus == 0); ilrun_tested = true; } if (ilrun_present) { unsigned int argc; char **argv; char **argp; unsigned int i; bool err; argc = 1 + 2 * libdirs_count + 1 + nargs; argv = (char **) xmalloca ((argc + 1) * sizeof (char *)); argp = argv; *argp++ = "ilrun"; for (i = 0; i < libdirs_count; i++) { *argp++ = "-L"; *argp++ = (char *) libdirs[i]; } *argp++ = (char *) assembly_path; for (i = 0; i < nargs; i++) *argp++ = (char *) args[i]; *argp = NULL; /* Ensure argv length was correctly calculated. */ if (argp - argv != argc) abort (); if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("ilrun", "ilrun", argv, private_data); freea (argv); return err; } else return -1; }
static int execute_csharp_using_mono (const char *assembly_path, const char * const *libdirs, unsigned int libdirs_count, const char * const *args, unsigned int nargs, bool verbose, bool quiet, execute_fn *executer, void *private_data) { static bool mono_tested; static bool mono_present; if (!mono_tested) { /* Test for presence of mono: "mono --version >/dev/null 2>/dev/null" */ char *argv[3]; int exitstatus; argv[0] = "mono"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("mono", "mono", argv, false, false, true, true, true, false, NULL); mono_present = (exitstatus == 0); mono_tested = true; } if (mono_present) { char *old_monopath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; bool err; /* Set MONO_PATH. */ old_monopath = set_monopath (libdirs, libdirs_count, false, verbose); argv[0] = "mono"; argv[1] = (char *) assembly_path; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("mono", "mono", argv, private_data); /* Reset MONO_PATH. */ reset_monopath (old_monopath); freea (argv); return err; } else return -1; }
bool execute_java_class (const char *class_name, const char * const *classpaths, unsigned int classpaths_count, bool use_minimal_classpath, const char *exe_dir, const char * const *args, bool verbose, bool quiet, execute_fn *executer, void *private_data) { bool err = false; unsigned int nargs; char *old_JAVA_HOME; /* Count args. */ { const char * const *arg; for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++) ; } /* First, try a class compiled to a native code executable. */ if (exe_dir != NULL) { char *exe_pathname = concatenated_filename (exe_dir, class_name, EXEEXT); char *old_classpath; char **argv = (char **) xmalloca ((1 + nargs + 1) * sizeof (char *)); unsigned int i; /* Set CLASSPATH. */ old_classpath = set_classpath (classpaths, classpaths_count, use_minimal_classpath, verbose); argv[0] = exe_pathname; for (i = 0; i <= nargs; i++) argv[1 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer (class_name, exe_pathname, argv, private_data); /* Reset CLASSPATH. */ reset_classpath (old_classpath); freea (argv); goto done1; } { const char *java = getenv ("JAVA"); if (java != NULL && java[0] != '\0') { /* Because $JAVA may consist of a command and options, we use the shell. Because $JAVA has been set by the user, we leave all all environment variables in place, including JAVA_HOME, and we don't erase the user's CLASSPATH. */ char *old_classpath; unsigned int command_length; char *command; char *argv[4]; const char * const *arg; char *p; /* Set CLASSPATH. */ old_classpath = set_classpath (classpaths, classpaths_count, false, verbose); command_length = strlen (java); command_length += 1 + shell_quote_length (class_name); for (arg = args; *arg != NULL; arg++) command_length += 1 + shell_quote_length (*arg); command_length += 1; command = (char *) xmalloca (command_length); p = command; /* Don't shell_quote $JAVA, because it may consist of a command and options. */ memcpy (p, java, strlen (java)); p += strlen (java); *p++ = ' '; p = shell_quote_copy (p, class_name); for (arg = args; *arg != NULL; arg++) { *p++ = ' '; p = shell_quote_copy (p, *arg); } *p++ = '\0'; /* Ensure command_length was correctly calculated. */ if (p - command > command_length) abort (); if (verbose) printf ("%s\n", command); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = command; argv[3] = NULL; err = executer (java, "/bin/sh", argv, private_data); freea (command); /* Reset CLASSPATH. */ reset_classpath (old_classpath); goto done1; } } /* Unset the JAVA_HOME environment variable. */ old_JAVA_HOME = getenv ("JAVA_HOME"); if (old_JAVA_HOME != NULL) { old_JAVA_HOME = xstrdup (old_JAVA_HOME); unsetenv ("JAVA_HOME"); } { static bool gij_tested; static bool gij_present; if (!gij_tested) { /* Test for presence of gij: "gij --version > /dev/null" */ char *argv[3]; int exitstatus; argv[0] = "gij"; argv[1] = "--version"; argv[2] = NULL; exitstatus = execute ("gij", "gij", argv, false, false, true, true, true, false); gij_present = (exitstatus == 0); gij_tested = true; } if (gij_present) { char *old_classpath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; /* Set CLASSPATH. */ old_classpath = set_classpath (classpaths, classpaths_count, use_minimal_classpath, verbose); argv[0] = "gij"; argv[1] = (char *) class_name; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("gij", "gij", argv, private_data); /* Reset CLASSPATH. */ reset_classpath (old_classpath); freea (argv); goto done2; } } { static bool java_tested; static bool java_present; if (!java_tested) { /* Test for presence of java: "java -version 2> /dev/null" */ char *argv[3]; int exitstatus; argv[0] = "java"; argv[1] = "-version"; argv[2] = NULL; exitstatus = execute ("java", "java", argv, false, false, true, true, true, false); java_present = (exitstatus == 0); java_tested = true; } if (java_present) { char *old_classpath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; /* Set CLASSPATH. We don't use the "-classpath ..." option because in JDK 1.1.x its argument should also contain the JDK's classes.zip, but we don't know its location. (In JDK 1.3.0 it would work.) */ old_classpath = set_classpath (classpaths, classpaths_count, use_minimal_classpath, verbose); argv[0] = "java"; argv[1] = (char *) class_name; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("java", "java", argv, private_data); /* Reset CLASSPATH. */ reset_classpath (old_classpath); freea (argv); goto done2; } } { static bool jre_tested; static bool jre_present; if (!jre_tested) { /* Test for presence of jre: "jre 2> /dev/null ; test $? = 1" */ char *argv[2]; int exitstatus; argv[0] = "jre"; argv[1] = NULL; exitstatus = execute ("jre", "jre", argv, false, false, true, true, true, false); jre_present = (exitstatus == 0 || exitstatus == 1); jre_tested = true; } if (jre_present) { char *old_classpath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; /* Set CLASSPATH. We don't use the "-classpath ..." option because in JDK 1.1.x its argument should also contain the JDK's classes.zip, but we don't know its location. */ old_classpath = set_classpath (classpaths, classpaths_count, use_minimal_classpath, verbose); argv[0] = "jre"; argv[1] = (char *) class_name; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("jre", "jre", argv, private_data); /* Reset CLASSPATH. */ reset_classpath (old_classpath); freea (argv); goto done2; } } #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ /* Win32, Cygwin */ { static bool jview_tested; static bool jview_present; if (!jview_tested) { /* Test for presence of jview: "jview -? >nul ; test $? = 1" */ char *argv[3]; int exitstatus; argv[0] = "jview"; argv[1] = "-?"; argv[2] = NULL; exitstatus = execute ("jview", "jview", argv, false, false, true, true, true, false); jview_present = (exitstatus == 0 || exitstatus == 1); jview_tested = true; } if (jview_present) { char *old_classpath; char **argv = (char **) xmalloca ((2 + nargs + 1) * sizeof (char *)); unsigned int i; /* Set CLASSPATH. */ old_classpath = set_classpath (classpaths, classpaths_count, use_minimal_classpath, verbose); argv[0] = "jview"; argv[1] = (char *) class_name; for (i = 0; i <= nargs; i++) argv[2 + i] = (char *) args[i]; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } err = executer ("jview", "jview", argv, private_data); /* Reset CLASSPATH. */ reset_classpath (old_classpath); freea (argv); goto done2; } } #endif if (!quiet) error (0, 0, _("Java virtual machine not found, try installing gij or set $JAVA")); err = true; done2: if (old_JAVA_HOME != NULL) { xsetenv ("JAVA_HOME", old_JAVA_HOME, 1); free (old_JAVA_HOME); } done1: return err; }
msgdomain_list_ty * msgdomain_read_tcl (const char *locale_name, const char *directory) { const char *gettextdatadir; char *tclscript; size_t len; char *frobbed_locale_name; char *p; char *file_name; char *argv[4]; pid_t child; int fd[1]; FILE *fp; msgdomain_list_ty *mdlp; int exitstatus; size_t k; /* Make it possible to override the msgunfmt.tcl location. This is necessary for running the testsuite before "make install". */ gettextdatadir = getenv ("GETTEXTDATADIR"); if (gettextdatadir == NULL || gettextdatadir[0] == '\0') gettextdatadir = relocate (GETTEXTDATADIR); tclscript = xconcatenated_filename (gettextdatadir, "msgunfmt.tcl", NULL); /* Convert the locale name to lowercase and remove any encoding. */ len = strlen (locale_name); frobbed_locale_name = (char *) xmalloca (len + 1); memcpy (frobbed_locale_name, locale_name, len + 1); for (p = frobbed_locale_name; *p != '\0'; p++) if (*p >= 'A' && *p <= 'Z') *p = *p - 'A' + 'a'; else if (*p == '.') { *p = '\0'; break; } file_name = xconcatenated_filename (directory, frobbed_locale_name, ".msg"); freea (frobbed_locale_name); /* Prepare arguments. */ argv[0] = "tclsh"; argv[1] = tclscript; argv[2] = file_name; argv[3] = NULL; if (verbose) { char *command = shell_quote_argv (argv); printf ("%s\n", command); free (command); } /* Open a pipe to the Tcl interpreter. */ child = create_pipe_in ("tclsh", "tclsh", argv, DEV_NULL, false, true, true, fd); fp = fdopen (fd[0], "r"); if (fp == NULL) error (EXIT_FAILURE, errno, _("fdopen() failed")); /* Read the message list. */ mdlp = read_catalog_stream (fp, "(pipe)", "(pipe)", &input_format_po); fclose (fp); /* Remove zombie process from process list, and retrieve exit status. */ exitstatus = wait_subprocess (child, "tclsh", false, false, true, true, NULL); if (exitstatus != 0) { if (exitstatus == 2) /* Special exitcode provided by msgunfmt.tcl. */ error (EXIT_FAILURE, ENOENT, _("error while opening \"%s\" for reading"), file_name); else error (EXIT_FAILURE, 0, _("%s subprocess failed with exit code %d"), "tclsh", exitstatus); } free (tclscript); /* Move the header entry to the beginning. */ for (k = 0; k < mdlp->nitems; k++) { message_list_ty *mlp = mdlp->item[k]->messages; size_t j; for (j = 0; j < mlp->nitems; j++) if (is_header (mlp->item[j])) { /* Found the header entry. */ if (j > 0) { message_ty *header = mlp->item[j]; size_t i; for (i = j; i > 0; i--) mlp->item[i] = mlp->item[i - 1]; mlp->item[0] = header; } break; } } return mdlp; }
/* Return true if a format is a valid choiceFormatPattern. Extracts argument type information into spec. */ static bool choice_format_parse (const char *format, struct spec *spec, char **invalid_reason) { /* Pattern syntax: pattern := | choice | choice '|' pattern choice := number separator messageformat separator := '<' | '#' | '\u2264' Single-quote starts a quoted section, to be terminated at the next single-quote or string end. Double single-quote gives a single single-quote. */ bool quoting = false; HANDLE_QUOTE; if (*format == '\0') return true; for (;;) { /* Don't bother looking too precisely into the syntax of the number. It can contain various Unicode characters. */ bool number_nonempty; char *msgformat; char *mp; bool msgformat_valid; /* Parse number. */ number_nonempty = false; while (*format != '\0' && !(!quoting && (*format == '<' || *format == '#' || strncmp (format, "\\u2264", 6) == 0 || *format == '|'))) { if (format[0] == '\\') { if (format[1] == 'u' && c_isxdigit (format[2]) && c_isxdigit (format[3]) && c_isxdigit (format[4]) && c_isxdigit (format[5])) format += 6; else format += 2; } else format += 1; number_nonempty = true; HANDLE_QUOTE; } /* Short clause at end of pattern is valid and is ignored! */ if (*format == '\0') break; if (!number_nonempty) { *invalid_reason = xasprintf (_("In the directive number %u, a choice contains no number."), spec->directives); return false; } if (*format == '<' || *format == '#') format += 1; else if (strncmp (format, "\\u2264", 6) == 0) format += 6; else { *invalid_reason = xasprintf (_("In the directive number %u, a choice contains a number that is not followed by '<', '#' or '%s'."), spec->directives, "\\u2264"); return false; } HANDLE_QUOTE; msgformat = (char *) xmalloca (strlen (format) + 1); mp = msgformat; while (*format != '\0' && !(!quoting && *format == '|')) { *mp++ = *format++; HANDLE_QUOTE; } *mp = '\0'; msgformat_valid = message_format_parse (msgformat, NULL, spec, invalid_reason); freea (msgformat); if (!msgformat_valid) return false; if (*format == '\0') break; format++; HANDLE_QUOTE; } return true; }
/* Return true if a format is a valid messageFormatPattern. Extracts argument type information into spec. */ static bool message_format_parse (const char *format, char *fdi, struct spec *spec, char **invalid_reason) { const char *const format_start = format; bool quoting = false; for (;;) { HANDLE_QUOTE; if (!quoting && *format == '{') { unsigned int depth; const char *element_start; const char *element_end; size_t n; char *element_alloced; char *element; unsigned int number; enum format_arg_type type; FDI_SET (format, FMTDIR_START); spec->directives++; element_start = ++format; depth = 0; for (; *format != '\0'; format++) { if (*format == '{') depth++; else if (*format == '}') { if (depth == 0) break; else depth--; } } if (*format == '\0') { *invalid_reason = xstrdup (_("The string ends in the middle of a directive: found '{' without matching '}'.")); FDI_SET (format - 1, FMTDIR_ERROR); return false; } element_end = format++; n = element_end - element_start; element = element_alloced = (char *) xmalloca (n + 1); memcpy (element, element_start, n); element[n] = '\0'; if (!c_isdigit (*element)) { *invalid_reason = xasprintf (_("In the directive number %u, '{' is not followed by an argument number."), spec->directives); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } number = 0; do { number = 10 * number + (*element - '0'); element++; } while (c_isdigit (*element)); type = FAT_OBJECT; if (*element == '\0') ; else if (strncmp (element, ",time", 5) == 0 || strncmp (element, ",date", 5) == 0) { type = FAT_DATE; element += 5; if (*element == '\0') ; else if (*element == ',') { element++; if (strcmp (element, "short") == 0 || strcmp (element, "medium") == 0 || strcmp (element, "long") == 0 || strcmp (element, "full") == 0 || date_format_parse (element)) ; else { *invalid_reason = xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid date/time style."), spec->directives, element); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else { *element = '\0'; element -= 4; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else if (strncmp (element, ",number", 7) == 0) { type = FAT_NUMBER; element += 7; if (*element == '\0') ; else if (*element == ',') { element++; if (strcmp (element, "currency") == 0 || strcmp (element, "percent") == 0 || strcmp (element, "integer") == 0 || number_format_parse (element)) ; else { *invalid_reason = xasprintf (_("In the directive number %u, the substring \"%s\" is not a valid number style."), spec->directives, element); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else { *element = '\0'; element -= 6; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else if (strncmp (element, ",choice", 7) == 0) { type = FAT_NUMBER; /* because ChoiceFormat extends NumberFormat */ element += 7; if (*element == '\0') ; else if (*element == ',') { element++; if (choice_format_parse (element, spec, invalid_reason)) ; else { FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else { *element = '\0'; element -= 6; *invalid_reason = xasprintf (_("In the directive number %u, \"%s\" is not followed by a comma."), spec->directives, element); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } } else { *invalid_reason = xasprintf (_("In the directive number %u, the argument number is not followed by a comma and one of \"%s\", \"%s\", \"%s\", \"%s\"."), spec->directives, "time", "date", "number", "choice"); FDI_SET (format - 1, FMTDIR_ERROR); freea (element_alloced); return false; } freea (element_alloced); if (spec->allocated == spec->numbered_arg_count) { spec->allocated = 2 * spec->allocated + 1; spec->numbered = (struct numbered_arg *) xrealloc (spec->numbered, spec->allocated * sizeof (struct numbered_arg)); } spec->numbered[spec->numbered_arg_count].number = number; spec->numbered[spec->numbered_arg_count].type = type; spec->numbered_arg_count++; FDI_SET (format - 1, FMTDIR_END); } /* The doc says "ab}de" is invalid. Even though JDK accepts it. */ else if (!quoting && *format == '}') { FDI_SET (format, FMTDIR_START); *invalid_reason = xstrdup (_("The string starts in the middle of a directive: found '}' without matching '{'.")); FDI_SET (format, FMTDIR_ERROR); return false; } else if (*format != '\0') format++; else break; } return true; }