/************************************************************************ * * util.cpp - Utility function definitions for the exec utility * * $Id: util.cpp 590510 2007-10-30 23:30:35Z sebor $ * ************************************************************************ * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * **************************************************************************/ #include /* for assert */ #include /* for errno */ #include /* for sigaction(), signal() */ #include /* for vfprintf */ #include /* for exit, malloc */ #include /* for va_* */ #include /* for strerror */ #include /* for stat() */ #include /* for size_t */ #ifndef _WIN32 # include /* for sleep() */ #else # include /* for Sleep() */ #endif /* _WIN{32,64} */ #include "cmdopt.h" /* for exe_name, target_name */ #include "util.h" #ifdef _WIN32 # define DEV_NULL "NUL:" #else # define DEV_NULL "/dev/null" #endif // _WIN32 void warn (const char* const format, ...) { const char* const target_name = get_target (); va_list args; assert (0 != format); if (target_name) fprintf (stderr, "%s (%s): ", exe_name, target_name); else fprintf (stderr, "%s: ", exe_name); va_start (args, format); vfprintf (stderr, format, args); va_end (args); } void terminate (const int state, const char* const format, ...) { const char* const target_name = get_target (); va_list args; assert (0 != format); assert (0 != state); if (target_name) fprintf (stderr, "%s (%s): ", exe_name, target_name); else fprintf (stderr, "%s: ", exe_name); va_start (args, format); vfprintf (stderr, format, args); va_end (args); exit (state); } void* guarded_malloc (const size_t size, const char* const file, const unsigned line) { void* alloc; assert (0 != file); assert (0 < size); alloc = malloc (size); if (0 == alloc) terminate (1, "malloc (%lu) at line %u of %s failed: %s\n", (unsigned long)size, line, file, strerror (errno)); return alloc; } void* guarded_realloc (void* source, const size_t size, const char* const file, const unsigned line) { void* alloc; assert (0 != file); assert (0 < size); alloc = realloc (source, size); if (0 == alloc) terminate (1, "malloc(%lu) at line %u of %s failed: %s\n", (unsigned long)size, line, file, strerror (errno)); return alloc; } char* reference_name (const char* data_dir, const char* subdir, const char* mode) { size_t root_len, cmp_len, dir_len, mode_len, net_len; char* ref_name; char* tail; const char* const target_name = get_target (); assert (0 != target_name); assert (0 != subdir); assert (0 != mode); root_len = data_dir ? strlen (data_dir) : 0; cmp_len = strlen (target_name) - exe_suffix_len; dir_len = strlen (subdir); mode_len = strlen (mode); net_len = root_len + cmp_len + dir_len + mode_len * 2 + 5; /* 5 comes from 3 path seperator characters, the suffix seperator character, and the trailing null */ tail = ref_name = (char*)RW_MALLOC (net_len); memcpy (tail, data_dir, root_len); tail += root_len; *tail++ = default_path_sep; memcpy (tail , subdir, dir_len); tail += dir_len; *tail++ = default_path_sep; memcpy (tail , mode, mode_len); tail += mode_len; *tail++ = default_path_sep; memcpy (tail , target_name, cmp_len); tail += cmp_len; *tail++ = suffix_sep; memcpy (tail , mode, mode_len); tail += mode_len; *tail = '\0'; return ref_name; } /** Composes the name of an input file, based on target Takes a data directory and an executable name, and tries to open an input file based on these variables. If a file is found in neither of two locattions derived from these variables, this method tries to fall back on /dev/null. Source file locations: - [data_dir]/manual/in/[target].in - [data_dir]/tutorial/in/[target].in - /dev/null @param data_dir the path of the reference data directory @param target the name of executable being run @returns the name of the file */ char* input_name (const char* data_dir, const char* target) { char* fname = 0; int stat_result = 0; struct stat sb; assert (0 != target); if (data_dir && *data_dir) { /* Try data_dir/manual/in/target.in */ fname = reference_name (data_dir, "manual", "in"); stat_result = stat (fname, &sb); if (0 == stat_result) return fname; free (fname); /* Try data_dir/tutorial/in/target.in */ fname = reference_name (data_dir, "tutorial", "in"); stat_result = stat (fname, &sb); if (0 == stat_result) return fname; free (fname); } /* If we didn't find a source file, use /dev/null */ fname = (char*)RW_MALLOC (sizeof DEV_NULL); strcpy (fname, DEV_NULL); return fname; } char* output_name (const char* target) { const char* suffix = "out"; const size_t sfx_len = strlen (suffix); const size_t exe_len = strlen (target) - exe_suffix_len; char* const tmp_name = (char*)RW_MALLOC (exe_len + sfx_len + 2); memcpy (tmp_name, target, exe_len); *(tmp_name + exe_len) = suffix_sep; memcpy (tmp_name + exe_len + 1, suffix, sfx_len + 1); return tmp_name; } #ifndef _WIN32 void rw_sleep (int seconds) { sleep (seconds); } # ifndef _RWSTD_EDG_ECCP # ifdef __cplusplus extern "C" { # endif /* __cplusplus */ int rw_signal (int signo, void (*func)(int)) { struct sigaction act; memset (&act, 0, sizeof act); /* avoid extern "C"/"C++" mismatch due to an HP aCC 6 bug (see STDCXX-291) */ if (func) memcpy (&act.sa_handler, &func, sizeof func); else act.sa_handler = 0; return 0 > sigaction (signo, &act, 0); } # ifdef __cplusplus } /* extern "C" */ # endif /* __cplusplus */ # else /* if defined (_RWSTD_EDG_ECCP) */ # ifdef __cplusplus extern "C" { # endif /* __cplusplus */ int rw_signal (int signo, void (*func)(int)) { return SIG_ERR == signal (signo, func); } # ifdef __cplusplus } /* extern "C" */ # endif /* __cplusplus */ # endif /* _RWSTD_EDG_ECCP */ #else /* if defined (_WIN32) || defined (_WIN64) */ void rw_sleep (int seconds) { Sleep (seconds * 1000); } int rw_signal (int signo, void (*func)(int)) { return SIG_ERR == signal (signo, func); } #endif /* _WIN32 */