http://git-wip-us.apache.org/repos/asf/lucy-charmonizer/blob/6adc7977/tests/charmonizer.c ---------------------------------------------------------------------- diff --git a/tests/charmonizer.c b/tests/charmonizer.c new file mode 100644 index 0000000..12bb2d9 --- /dev/null +++ b/tests/charmonizer.c @@ -0,0 +1,7910 @@ +/* This is an auto-generated file -- do not edit directly. */ + +/* 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. + */ + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/Defines.h" +/* Charmonizer/Core/Defines.h -- Universal definitions. + */ +#ifndef H_CHAZ_DEFINES +#define H_CHAZ_DEFINES 1 + +#ifndef true + #define true 1 + #define false 0 +#endif + +#define CHAZ_QUOTE(x) #x "\n" + +#endif /* H_CHAZ_DEFINES */ + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/Library.h" +/* Charmonizer/Core/Library.h + */ + +#ifndef H_CHAZ_LIB +#define H_CHAZ_LIB + +typedef struct chaz_Lib chaz_Lib; + +typedef enum { + chaz_Lib_SHARED = 1, + chaz_Lib_STATIC = 2 +} chaz_LibType; + +chaz_Lib* +chaz_Lib_new(const char *name, chaz_LibType type, const char *version, + const char *major_version); + +void +chaz_Lib_destroy(chaz_Lib *flags); + +const char* +chaz_Lib_get_name(chaz_Lib *lib); + +const char* +chaz_Lib_get_version(chaz_Lib *lib); + +const char* +chaz_Lib_get_major_version(chaz_Lib *lib); + +int +chaz_Lib_is_shared(chaz_Lib *lib); + +int +chaz_Lib_is_static(chaz_Lib *lib); + +char* +chaz_Lib_filename(chaz_Lib *lib); + +char* +chaz_Lib_major_version_filename(chaz_Lib *lib); + +char* +chaz_Lib_no_version_filename(chaz_Lib *lib); + +char* +chaz_Lib_implib_filename(chaz_Lib *lib); + +char* +chaz_Lib_export_filename(chaz_Lib *lib); + +#endif /* H_CHAZ_LIB */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/CFlags.h" +/* Charmonizer/Core/CFlags.h + */ + +#ifndef H_CHAZ_CFLAGS +#define H_CHAZ_CFLAGS + +/* #include "Charmonizer/Core/Library.h" */ + +#define CHAZ_CFLAGS_STYLE_POSIX 1 +#define CHAZ_CFLAGS_STYLE_GNU 2 +#define CHAZ_CFLAGS_STYLE_MSVC 3 +#define CHAZ_CFLAGS_STYLE_SUN_C 4 + +typedef struct chaz_CFlags chaz_CFlags; + +chaz_CFlags* +chaz_CFlags_new(int style); + +void +chaz_CFlags_destroy(chaz_CFlags *flags); + +const char* +chaz_CFlags_get_string(chaz_CFlags *flags); + +void +chaz_CFlags_append(chaz_CFlags *flags, const char *string); + +void +chaz_CFlags_clear(chaz_CFlags *flags); + +void +chaz_CFlags_set_output_obj(chaz_CFlags *flags, const char *filename); + +void +chaz_CFlags_set_output_exe(chaz_CFlags *flags, const char *filename); + +void +chaz_CFlags_add_define(chaz_CFlags *flags, const char *name, + const char *value); + +void +chaz_CFlags_add_include_dir(chaz_CFlags *flags, const char *dir); + +void +chaz_CFlags_enable_optimization(chaz_CFlags *flags); + +void +chaz_CFlags_disable_strict_aliasing(chaz_CFlags *flags); + +void +chaz_CFlags_set_warnings_as_errors(chaz_CFlags *flags); + +void +chaz_CFlags_compile_shared_library(chaz_CFlags *flags); + +void +chaz_CFlags_hide_symbols(chaz_CFlags *flags); + +void +chaz_CFlags_link_shared_library(chaz_CFlags *flags); + +void +chaz_CFlags_set_shared_library_version(chaz_CFlags *flags, chaz_Lib *lib); + +void +chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename); + +void +chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory); + +void +chaz_CFlags_add_library(chaz_CFlags *flags, chaz_Lib *lib); + +void +chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library); + +void +chaz_CFlags_enable_code_coverage(chaz_CFlags *flags); + +#endif /* H_CHAZ_CFLAGS */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/CLI.h" +#ifndef H_CHAZ_CLI +#define H_CHAZ_CLI 1 + +#define CHAZ_CLI_NO_ARG 0 +#define CHAZ_CLI_ARG_REQUIRED (1 << 0) +#define CHAZ_CLI_ARG_OPTIONAL (1 << 1) + +/* The CLI module provides argument parsing for a command line interface. + */ + +typedef struct chaz_CLI chaz_CLI; + +/* Constructor. + * + * @param name The name of the application. + * @param description A description of the application. + */ +chaz_CLI* +chaz_CLI_new(const char *name, const char *description); + +/* Destructor. + */ +void +chaz_CLI_destroy(chaz_CLI *self); + +/* Return a string combining usage header with documentation of options. + */ +const char* +chaz_CLI_help(chaz_CLI *self); + +/* Override the generated usage header. + */ +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage); + +/* Register an option. Updates the "help" string, invalidating previous + * values. Returns true on success, or reports an error and returns false if + * the option was already registered. + */ +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags); + +/* Set an option. The specified option must have been registered previously. + * The supplied `value` is optional and will be copied. + * + * Returns true on success. Reports an error and returns false on failure. + */ +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value); + +/* Returns true if the option has been set, false otherwise. + */ +int +chaz_CLI_defined(chaz_CLI *self, const char *name); + +/* Return the value of a given option converted to a long int. Defaults to 0. + * Reports an error if the named option has not been registered. + */ +long +chaz_CLI_longval(chaz_CLI *self, const char *name); + +/* Return the value of an option as a C string. Defaults to NULL. Reports an + * error if the named option has not been registered. + */ +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name); + +/* Unset an option, making subsequent calls to `get` return false and making + * it possible to call `set` again. + * + * Returns true if the option exists and was able to be unset. + */ +int +chaz_CLI_unset(chaz_CLI *self, const char *name); + +/* Parse `argc` and `argv`, setting options as appropriate. Returns true on + * success. Reports an error and returns false if either an unexpected option + * was encountered or an option which requires an argument was supplied + * without one. + */ +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]); + +#endif /* H_CHAZ_CLI */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/Compiler.h" +/* Charmonizer/Core/Compiler.h + */ + +#ifndef H_CHAZ_COMPILER +#define H_CHAZ_COMPILER + +#include <stddef.h> +/* #include "Charmonizer/Core/Defines.h" */ +/* #include "Charmonizer/Core/CFlags.h" */ + +/* Attempt to compile and link an executable. Return true if the executable + * file exists after the attempt. + */ +int +chaz_CC_compile_exe(const char *source_path, const char *exe_path, + const char *code); + +/* Attempt to compile an object file. Return true if the object file + * exists after the attempt. + */ +int +chaz_CC_compile_obj(const char *source_path, const char *obj_path, + const char *code); + +/* Attempt to compile the supplied source code and return true if the + * effort succeeds. + */ +int +chaz_CC_test_compile(const char *source); + +/* Attempt to compile the supplied source code. If successful, capture the + * output of the program and return a pointer to a newly allocated buffer. + * If the compilation fails, return NULL. The length of the captured + * output will be placed into the integer pointed to by [output_len]. + */ +char* +chaz_CC_capture_output(const char *source, size_t *output_len); + +/** Initialize the compiler environment. + */ +void +chaz_CC_init(const char *cc_command, const char *cflags); + +/* Clean up the environment. + */ +void +chaz_CC_clean_up(void); + +/* Accessor for the compiler executable's string representation. + */ +const char* +chaz_CC_get_cc(void); + +/* Accessor for `cflags`. + */ +const char* +chaz_CC_get_cflags(void); + +/* Accessor for `extra_cflags`. + */ +chaz_CFlags* +chaz_CC_get_extra_cflags(void); + +/* Accessor for `temp_cflags`. + */ +chaz_CFlags* +chaz_CC_get_temp_cflags(void); + +/* Return a new CFlags object. + */ +chaz_CFlags* +chaz_CC_new_cflags(void); + +/* Return the extension for a compiled object. + */ +const char* +chaz_CC_obj_ext(void); + +int +chaz_CC_gcc_version_num(void); + +const char* +chaz_CC_gcc_version(void); + +int +chaz_CC_msvc_version_num(void); + +int +chaz_CC_sun_c_version_num(void); + +const char* +chaz_CC_link_command(void); + +/* Create a command for building a static library. + * + * @param target The target library filename. + * @param objects The list of object files to be archived in the library. + */ +char* +chaz_CC_format_archiver_command(const char *target, const char *objects); + +/* Returns a "ranlib" command if valid. + * + * @param target The library filename. + */ +char* +chaz_CC_format_ranlib_command(const char *target); + +#endif /* H_CHAZ_COMPILER */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/ConfWriter.h" +/* Charmonizer/Core/ConfWriter.h -- Write to a config file. + */ + +#ifndef H_CHAZ_CONFWRITER +#define H_CHAZ_CONFWRITER 1 + +#include <stddef.h> +#include <stdarg.h> +/* #include "Charmonizer/Core/Defines.h" */ + +struct chaz_ConfWriter; + +/* Initialize elements needed by ConfWriter. Must be called before anything + * else, but after os and compiler are initialized. + */ +void +chaz_ConfWriter_init(void); + +/* Close the include guard on charmony.h, then close the file. Delete temp + * files and perform any other needed cleanup. + */ +void +chaz_ConfWriter_clean_up(void); + +/* Print output to charmony.h. + */ +void +chaz_ConfWriter_append_conf(const char *fmt, ...); + +/* Add a pound-define. + */ +void +chaz_ConfWriter_add_def(const char *sym, const char *value); + +/* Add a globally scoped pound-define. + */ +void +chaz_ConfWriter_add_global_def(const char *sym, const char *value); + +/* Add a typedef. + */ +void +chaz_ConfWriter_add_typedef(const char *type, const char *alias); + +/* Add a globally scoped typedef. + */ +void +chaz_ConfWriter_add_global_typedef(const char *type, const char *alias); + +/* Pound-include a system header (within angle brackets). + */ +void +chaz_ConfWriter_add_sys_include(const char *header); + +/* Pound-include a locally created header (within quotes). + */ +void +chaz_ConfWriter_add_local_include(const char *header); + +/* Print a "chapter heading" comment in the conf file when starting a module. + */ +void +chaz_ConfWriter_start_module(const char *module_name); + +/* Leave a little whitespace at the end of each module. + */ +void +chaz_ConfWriter_end_module(void); + +void +chaz_ConfWriter_add_writer(struct chaz_ConfWriter *writer); + +typedef void +(*chaz_ConfWriter_clean_up_t)(void); +typedef void +(*chaz_ConfWriter_vappend_conf_t)(const char *fmt, va_list args); +typedef void +(*chaz_ConfWriter_add_def_t)(const char *sym, const char *value); +typedef void +(*chaz_ConfWriter_add_global_def_t)(const char *sym, const char *value); +typedef void +(*chaz_ConfWriter_add_typedef_t)(const char *type, const char *alias); +typedef void +(*chaz_ConfWriter_add_global_typedef_t)(const char *type, const char *alias); +typedef void +(*chaz_ConfWriter_add_sys_include_t)(const char *header); +typedef void +(*chaz_ConfWriter_add_local_include_t)(const char *header); +typedef void +(*chaz_ConfWriter_start_module_t)(const char *module_name); +typedef void +(*chaz_ConfWriter_end_module_t)(void); +typedef struct chaz_ConfWriter { + chaz_ConfWriter_clean_up_t clean_up; + chaz_ConfWriter_vappend_conf_t vappend_conf; + chaz_ConfWriter_add_def_t add_def; + chaz_ConfWriter_add_global_def_t add_global_def; + chaz_ConfWriter_add_typedef_t add_typedef; + chaz_ConfWriter_add_global_typedef_t add_global_typedef; + chaz_ConfWriter_add_sys_include_t add_sys_include; + chaz_ConfWriter_add_local_include_t add_local_include; + chaz_ConfWriter_start_module_t start_module; + chaz_ConfWriter_end_module_t end_module; +} chaz_ConfWriter; + +#endif /* H_CHAZ_CONFWRITER */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/ConfWriterC.h" +/* Charmonizer/Core/ConfWriterC.h -- Write to a C header file. + */ + +#ifndef H_CHAZ_CONFWRITERC +#define H_CHAZ_CONFWRITERC 1 + +/* Enable writing config to a C header file. + */ +void +chaz_ConfWriterC_enable(void); + +#endif /* H_CHAZ_CONFWRITERC */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/ConfWriterPerl.h" +/* Charmonizer/Core/ConfWriterPerl.h -- Write to a Perl module file. + */ + +#ifndef H_CHAZ_CONFWRITERPERL +#define H_CHAZ_CONFWRITERPERL 1 + +/* Enable writing config to a Perl module file. + */ +void +chaz_ConfWriterPerl_enable(void); + +#endif /* H_CHAZ_CONFWRITERPERL */ + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/ConfWriterPython.h" +/* Charmonizer/Core/ConfWriterPython.h -- Write to a Python module file. + */ + +#ifndef H_CHAZ_CONFWRITERPYTHON +#define H_CHAZ_CONFWRITERPYTHON 1 + +/* Enable writing config to a Python module file. + */ +void +chaz_ConfWriterPython_enable(void); + +#endif /* H_CHAZ_CONFWRITERPYTHON */ + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/ConfWriterRuby.h" +/* Charmonizer/Core/ConfWriterRuby.h -- Write to a Ruby module file. + */ + +#ifndef H_CHAZ_CONFWRITERRUBY +#define H_CHAZ_CONFWRITERRUBY 1 + +/* Enable writing config to a Ruby module file. + */ +void +chaz_ConfWriterRuby_enable(void); + +#endif /* H_CHAZ_CONFWRITERRUBY */ + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/HeaderChecker.h" +/* Charmonizer/Probe/HeaderChecker.h + */ + +#ifndef H_CHAZ_HEAD_CHECK +#define H_CHAZ_HEAD_CHECK + +/* #include "Charmonizer/Core/Defines.h" */ + +/* Bootstrap the HeadCheck. Call this before anything else. + */ +void +chaz_HeadCheck_init(void); + +/* Check for a particular header and return true if it's available. The + * test-compile is only run the first time a given request is made. + */ +int +chaz_HeadCheck_check_header(const char *header_name); + +/* Attempt to compile a file which pulls in all the headers specified by name + * in a null-terminated array. If the compile succeeds, add them all to the + * internal register and return true. + */ +int +chaz_HeadCheck_check_many_headers(const char **header_names); + +/* Return true if the member is present in the struct. */ +int +chaz_HeadCheck_contains_member(const char *struct_name, const char *member, + const char *includes); + +#endif /* H_CHAZ_HEAD_CHECK */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/Make.h" +/* Charmonizer/Core/Make.h + */ + +#ifndef H_CHAZ_MAKE +#define H_CHAZ_MAKE + +/* #include "Charmonizer/Core/CFlags.h" */ +/* #include "Charmonizer/Core/Library.h" */ + +typedef struct chaz_MakeFile chaz_MakeFile; +typedef struct chaz_MakeVar chaz_MakeVar; +typedef struct chaz_MakeRule chaz_MakeRule; + +typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file, + void *context); + +/** Initialize the environment. + */ +void +chaz_Make_init(void); + +/** Clean up the environment. + */ +void +chaz_Make_clean_up(void); + +/** Return the name of the detected 'make' executable. + */ +const char* +chaz_Make_get_make(void); + +/** Return the type of shell used by the detected 'make' executable. + */ +int +chaz_Make_shell_type(void); + +/** Recursively list files in a directory. For every file a callback is called + * with the filename and a context variable. + * + * @param dir Directory to search in. + * @param ext File extension to search for. + * @param callback Callback to call for every matching file. + * @param context Context variable to pass to callback. + */ +void +chaz_Make_list_files(const char *dir, const char *ext, + chaz_Make_list_files_callback_t callback, void *context); + +/** MakeFile constructor. + */ +chaz_MakeFile* +chaz_MakeFile_new(); + +/** MakeFile destructor. + */ +void +chaz_MakeFile_destroy(chaz_MakeFile *makefile); + +/** Add a variable to a makefile. + * + * @param makefile The makefile. + * @param name Name of the variable. + * @param value Value of the variable. Can be NULL if you want add content + * later. + * @return a MakeVar. + */ +chaz_MakeVar* +chaz_MakeFile_add_var(chaz_MakeFile *makefile, const char *name, + const char *value); + +/** Add a rule to a makefile. + * + * @param makefile The makefile. + * @param target The first target of the rule. Can be NULL if you want to add + * targets later. + * @param prereq The first prerequisite of the rule. Can be NULL if you want to + * add prerequisites later. + * @return a MakeRule. + */ +chaz_MakeRule* +chaz_MakeFile_add_rule(chaz_MakeFile *makefile, const char *target, + const char *prereq); + +/** Return the rule for the 'clean' target. + * + * @param makefile The makefile. + */ +chaz_MakeRule* +chaz_MakeFile_clean_rule(chaz_MakeFile *makefile); + +/** Return the rule for the 'distclean' target. + * + * @param makefile The makefile. + */ +chaz_MakeRule* +chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile); + +/** Add a rule to link an executable. The executable will also be added to the + * list of files to clean. + * + * @param makefile The makefile. + * @param exe The name of the executable. + * @param sources The list of source files. + * @param link_flags Additional link flags. + */ +chaz_MakeRule* +chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe, + const char *sources, chaz_CFlags *link_flags); + +/** Add a rule to compile and link an executable. The executable will also be + * added to the list of files to clean. + * + * @param makefile The makefile. + * @param exe The name of the executable. + * @param sources The list of source files. + * @param cflags Additional compiler flags. + */ +chaz_MakeRule* +chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe, + const char *sources, chaz_CFlags *cflags); + +/** Add a rule to link a shared library. The shared library will also be added + * to the list of files to clean. + * + * @param makefile The makefile. + * @param lib The shared library. + * @param sources The list of source files. + * @param link_flags Additional link flags. + */ +chaz_MakeRule* +chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib, + const char *sources, chaz_CFlags *link_flags); + +/** Add a rule to create a static library. The static library will also be added + * to the list of files to clean. + * + * @param makefile The makefile. + * @param lib The static library. + * @param objects The list of object files to be archived. + */ +chaz_MakeRule* +chaz_MakeFile_add_static_lib(chaz_MakeFile *makefile, chaz_Lib *lib, + const char *objects); + +/** Add a rule to build the lemon parser generator. + * + * @param makefile The makefile. + * @param dir The lemon directory. + */ +chaz_MakeRule* +chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir); + +/** Add a rule for a lemon grammar. + * + * @param makefile The makefile. + * @param base_name The filename of the grammar without extension. + */ +chaz_MakeRule* +chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile, + const char *base_name); + +/** Write the makefile to a file named 'Makefile' in the current directory. + * + * @param makefile The makefile. + */ +void +chaz_MakeFile_write(chaz_MakeFile *makefile); + +/** Append content to a makefile variable. The new content will be separated + * from the existing content with whitespace. + * + * @param var The variable. + * @param element The additional content. + */ +void +chaz_MakeVar_append(chaz_MakeVar *var, const char *element); + +/** Add another target to a makefile rule. + * + * @param rule The rule. + * @param target The additional rule. + */ +void +chaz_MakeRule_add_target(chaz_MakeRule *rule, const char *target); + +/** Add another prerequisite to a makefile rule. + * + * @param rule The rule. + * @param prereq The additional prerequisite. + */ +void +chaz_MakeRule_add_prereq(chaz_MakeRule *rule, const char *prereq); + +/** Add a command to a rule. + * + * @param rule The rule. + * @param command The additional command. + */ +void +chaz_MakeRule_add_command(chaz_MakeRule *rule, const char *command); + +/** Add a command to remove one or more files. + * + * @param rule The rule. + * @param files The list of files. + */ +void +chaz_MakeRule_add_rm_command(chaz_MakeRule *rule, const char *files); + +/** Add a command to remove one or more directories. + * + * @param rule The rule. + * @param dirs The list of directories. + */ +void +chaz_MakeRule_add_recursive_rm_command(chaz_MakeRule *rule, const char *dirs); + +/** Add one or more commands to call another makefile recursively. + * + * @param rule The rule. + * @param dir The directory in which to call the makefile. + * @param target The target to call. Pass NULL for the default target. + */ +void +chaz_MakeRule_add_make_command(chaz_MakeRule *rule, const char *dir, + const char *target); + +#endif /* H_CHAZ_MAKE */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/OperatingSystem.h" +/* Charmonizer/Core/OperatingSystem.h - abstract an operating system down to a few + * variables. + */ + +#ifndef H_CHAZ_OPER_SYS +#define H_CHAZ_OPER_SYS + +#define CHAZ_OS_POSIX 1 +#define CHAZ_OS_CMD_EXE 2 + +/* Safely remove a file named [name]. Needed because of Windows quirks. + * Returns true on success, false on failure. + */ +int +chaz_OS_remove(const char *name); + +/* Invoke a command and attempt to suppress output from both stdout and stderr + * (as if they had been sent to /dev/null). If it's not possible to run the + * command quietly, run it anyway. + */ +int +chaz_OS_run_quietly(const char *command); + +/* Capture both stdout and stderr for a command to the supplied filepath. + */ +int +chaz_OS_run_redirected(const char *command, const char *path); + +/* Run a command beginning with the name of an executable in the current + * working directory and capture both stdout and stderr to the supplied + * filepath. + */ +int +chaz_OS_run_local_redirected(const char *command, const char *path); + +/* Run a command and return the output from stdout. + */ +char* +chaz_OS_run_and_capture(const char *command, size_t *output_len); + +/* Attempt to create a directory. + */ +void +chaz_OS_mkdir(const char *filepath); + +/* Attempt to remove a directory, which must be empty. + */ +void +chaz_OS_rmdir(const char *filepath); + +/* Return the operating system name. + */ +const char* +chaz_OS_name(void); + +int +chaz_OS_is_darwin(void); + +int +chaz_OS_is_cygwin(void); + +/* Return the extension for an executable on this system. + */ +const char* +chaz_OS_exe_ext(void); + +/* Return the extension for a shared object on this system. + */ +const char* +chaz_OS_shared_lib_ext(void); + +/* Return the extension for a static library on this system. + */ +const char* +chaz_OS_static_lib_ext(void); + +/* Return the equivalent of /dev/null on this system. + */ +const char* +chaz_OS_dev_null(void); + +/* Return the directory separator on this system. + */ +const char* +chaz_OS_dir_sep(void); + +/* Return the shell type of this system. + */ +int +chaz_OS_shell_type(void); + +/* Initialize the Charmonizer/Core/OperatingSystem module. + */ +void +chaz_OS_init(void); + +#endif /* H_CHAZ_COMPILER */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Core/Util.h" +/* Chaz/Core/Util.h -- miscellaneous utilities. + */ + +#ifndef H_CHAZ_UTIL +#define H_CHAZ_UTIL 1 + +#include <stdio.h> +#include <stddef.h> +#include <stdarg.h> + +extern int chaz_Util_verbosity; + +/* Open a file (truncating if necessary) and write [content] to it. Util_die() if + * an error occurs. + */ +void +chaz_Util_write_file(const char *filename, const char *content); + +/* Read an entire file into memory. + */ +char* +chaz_Util_slurp_file(const char *file_path, size_t *len_ptr); + +/* Return a newly allocated copy of a NULL-terminated string. + */ +char* +chaz_Util_strdup(const char *string); + +/* Join a NULL-terminated list of strings using a separator. + */ +char* +chaz_Util_join(const char *sep, ...); + +/* Get the length of a file (may overshoot on text files under DOS). + */ +long +chaz_Util_flength(void *file); + +/* Print an error message to stderr and exit. + */ +void +chaz_Util_die(const char *format, ...); + +/* Print an error message to stderr. + */ +void +chaz_Util_warn(const char *format, ...); + +/* Attept to delete a file. Return true if the file is gone, whether or not + * it was there to begin with. Issue a warning and return false if the file + * still exists. + */ +int +chaz_Util_remove_and_verify(const char *file_path); + +/* Attempt to open a file for reading, then close it immediately. + */ +int +chaz_Util_can_open_file(const char *file_path); + +#endif /* H_CHAZ_UTIL */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe.h" +#ifndef H_CHAZ +#define H_CHAZ 1 + +#include <stddef.h> +#include <stdio.h> + +struct chaz_CLI; + +/* Parse command line arguments, initializing and filling in the supplied + * `args` struct. + * + * APP_NAME --cc=CC_COMMAND + * [--enable-c] + * [--enable-perl] + * [--enable-python] + * [--enable-ruby] + * [-- [CFLAGS]] + * + * @return true if argument parsing proceeds without incident, false if + * unexpected arguments are encountered or values are missing or invalid. + */ +int +chaz_Probe_parse_cli_args(int argc, const char *argv[], + struct chaz_CLI *cli); + +/* Exit after printing usage instructions to stderr. + */ +void +chaz_Probe_die_usage(void); + +/* Set up the Charmonizer environment. + * + * If the environment variable CHARM_VERBOSITY has been set, it will be + * processed at this time: + * + * 0 - silent + * 1 - normal + * 2 - debugging + */ +void +chaz_Probe_init(struct chaz_CLI *cli); + +/* Clean up the Charmonizer environment -- deleting tempfiles, etc. This + * should be called only after everything else finishes. + */ +void +chaz_Probe_clean_up(void); + +/* Return an integer version of the GCC version number which is + * (10000 * __GNU_C__ + 100 * __GNUC_MINOR__ + __GNUC_PATCHLEVEL__). + */ +int +chaz_Probe_gcc_version_num(void); + +/* If the compiler is GCC (or claims compatibility), return an X.Y.Z string + * version of the GCC version; otherwise, return NULL. + */ +const char* +chaz_Probe_gcc_version(void); + +/* Return the integer version of MSVC defined by _MSC_VER + */ +int +chaz_Probe_msvc_version_num(void); + +#endif /* Include guard. */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/AtomicOps.h" +/* Charmonizer/Probe/AtomicOps.h + */ + +#ifndef H_CHAZ_ATOMICOPS +#define H_CHAZ_ATOMICOPS + +#include <stdio.h> + +/* Run the AtomicOps module. + * + * These following symbols will be defined if the associated headers are + * available: + * + * HAS_LIBKERN_OSATOMIC_H <libkern/OSAtomic.h> (Mac OS X) + * HAS_SYS_ATOMIC_H <sys/atomic.h> (Solaris) + * HAS_INTRIN_H <intrin.h> (Windows) + * + * This symbol is defined if OSAtomicCompareAndSwapPtr is available: + * + * HAS_OSATOMIC_CAS_PTR + */ +void chaz_AtomicOps_run(void); + +#endif /* H_CHAZ_ATOMICOPS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/Booleans.h" +/* Charmonizer/Probe/Booleans.h -- bool type. + * + * If stdbool.h is is available, it will be pound-included in the configuration + * header. If it is not, the following typedef will be defined: + * + * bool + * + * These symbols will be defined if they are not already: + * + * true + * false + */ + +#ifndef H_CHAZ_BOOLEANS +#define H_CHAZ_BOOLEANS + +#include <stdio.h> + +/* Run the Booleans module. + */ +void chaz_Booleans_run(void); + +#endif /* H_CHAZ_BOOLEANS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/BuildEnv.h" +/* Charmonizer/Probe/BuildEnv.h -- Build environment. + * + * Capture various information about the build environment, including the C + * compiler's interface, the shell, the operating system, etc. + * + * The following symbols will be defined: + * + * CC - String representation of the C compiler executable. + * CFLAGS - C compiler flags. + * EXTRA_CFLAGS - Extra C compiler flags. + */ + +#ifndef H_CHAZ_BUILDENV +#define H_CHAZ_BUILDENV + +#include <stdio.h> + +/* Run the BuildEnv module. + */ +void chaz_BuildEnv_run(void); + +#endif /* H_CHAZ_BUILDENV */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/DirManip.h" +/* Charmonizer/Probe/DirManip.h + */ + +#ifndef H_CHAZ_DIRMANIP +#define H_CHAZ_DIRMANIP + +/* The DirManip module exports or aliases symbols related to directory and file + * manipulation. + * + * Defined if the header files dirent.h and direct.h are available, respectively: + * + * HAS_DIRENT_H + * HAS_DIRECT_H + * + * Defined if struct dirent has these members. + * + * HAS_DIRENT_D_NAMLEN + * HAS_DIRENT_D_TYPE + * + * The "makedir" macro will be aliased to the POSIX-specified two-argument + * "mkdir" interface: + * + * makedir + * + * On some systems, the second argument to makedir will be ignored, in which + * case this symbol will be true; otherwise, it will be false: (TODO: This + * isn't verified and may sometimes be incorrect.) + * + * MAKEDIR_MODE_IGNORED + * + * String representing the system's directory separator: + * + * DIR_SEP + * + * True if the remove() function removes directories, false otherwise: + * + * REMOVE_ZAPS_DIRS + */ +void chaz_DirManip_run(void); + +#endif /* H_CHAZ_DIR_SEP */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/Floats.h" +/* Charmonizer/Probe/Floats.h -- floating point types. + * + * The following symbols will be created if the platform supports IEEE 754 + * floating point types: + * + * F32_NAN + * F32_INF + * F32_NEGINF + * F64_NAN + * F64_INF + * F64_NEGINF + * + * TODO: Actually test to see whether IEEE 754 is supported, rather than just + * lying about it. + */ + +#ifndef H_CHAZ_FLOATS +#define H_CHAZ_FLOATS + +/* Run the Floats module. + */ +void +chaz_Floats_run(void); + +/* Return the name of the math library to link against or NULL. + */ +const char* +chaz_Floats_math_library(void); + +#endif /* H_CHAZ_FLOATS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/FuncMacro.h" +/* Charmonizer/Probe/FuncMacro.h + */ + +#ifndef H_CHAZ_FUNC_MACRO +#define H_CHAZ_FUNC_MACRO + +#include <stdio.h> + +/* Run the FuncMacro module. + * + * If __func__ successfully resolves, this will be defined: + * + * HAS_ISO_FUNC_MACRO + * + * If __FUNCTION__ successfully resolves, this will be defined: + * + * HAS_GNUC_FUNC_MACRO + * + * If one or the other succeeds, these will be defined: + * + * HAS_FUNC_MACRO + * FUNC_MACRO + * + * The "inline" keyword will also be probed for. If it is available, the + * following macro will be defined to "inline", otherwise it will be defined + * to nothing. + * + * INLINE + */ +void chaz_FuncMacro_run(void); + +#endif /* H_CHAZ_FUNC_MACRO */ + + + + +/***************************************************************************/ + +#line 20 "src/Charmonizer/Probe/Headers.h" +/* Charmonizer/Probe/Headers.h + */ + +#ifndef H_CHAZ_HEADERS +#define H_CHAZ_HEADERS + +#include <stdio.h> +/* #include "Charmonizer/Core/Defines.h" */ + +/* Check whether a particular header file is available. The test-compile is + * only run the first time a given request is made. + */ +int +chaz_Headers_check(const char *header_name); + +/* Run the Headers module. + * + * Exported symbols: + * + * If HAS_C89 is declared, this system has all the header files described in + * Ansi C 1989. HAS_C90 is a synonym. (It would be surprising if they are + * not defined, because Charmonizer itself assumes C89.) + * + * HAS_C89 + * HAS_C90 + * + * One symbol is exported for each C89 header file: + * + * HAS_ASSERT_H + * HAS_CTYPE_H + * HAS_ERRNO_H + * HAS_FLOAT_H + * HAS_LIMITS_H + * HAS_LOCALE_H + * HAS_MATH_H + * HAS_SETJMP_H + * HAS_SIGNAL_H + * HAS_STDARG_H + * HAS_STDDEF_H + * HAS_STDIO_H + * HAS_STDLIB_H + * HAS_STRING_H + * HAS_TIME_H + * + * One symbol is exported for every POSIX header present, and HAS_POSIX is + * exported if they're all there. + * + * HAS_POSIX + * + * HAS_CPIO_H + * HAS_DIRENT_H + * HAS_FCNTL_H + * HAS_GRP_H + * HAS_PWD_H + * HAS_SYS_STAT_H + * HAS_SYS_TIMES_H + * HAS_SYS_TYPES_H + * HAS_SYS_UTSNAME_H + * HAS_WAIT_H + * HAS_TAR_H + * HAS_TERMIOS_H + * HAS_UNISTD_H + * HAS_UTIME_H + * + * If pthread.h is available, this will be exported: + * + * HAS_PTHREAD_H + */ +void +chaz_Headers_run(void); + +#endif /* H_CHAZ_HEADERS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/Integers.h" +/* Charmonizer/Probe/Integers.h -- info about integer types and sizes. + * + * One or the other of these will be defined, depending on whether the + * processor is big-endian or little-endian. + * + * BIG_END + * LITTLE_END + * + * These will always be defined: + * + * SIZEOF_CHAR + * SIZEOF_SHORT + * SIZEOF_INT + * SIZEOF_LONG + * SIZEOF_PTR + * + * If long longs are available these symbols will be defined: + * + * HAS_LONG_LONG + * SIZEOF_LONG_LONG + * + * Similarly, with the __int64 type (the sizeof is included for completeness): + * + * HAS___INT64 + * SIZEOF___INT64 + * + * If the inttypes.h or stdint.h header files are available, these may be + * defined: + * + * HAS_INTTYPES_H + * HAS_STDINT_H + * + * If stdint.h is is available, it will be pound-included in the configuration + * header. If it is not, the following typedefs and macros will be defined if + * possible: + * + * int8_t + * int16_t + * int32_t + * int64_t + * uint8_t + * uint16_t + * uint32_t + * uint64_t + * INT8_MAX + * INT16_MAX + * INT32_MAX + * INT64_MAX + * INT8_MIN + * INT16_MIN + * INT32_MIN + * INT64_MIN + * UINT8_MAX + * UINT16_MAX + * UINT32_MAX + * UINT64_MAX + * SIZE_MAX + * INT32_C + * INT64_C + * UINT32_C + * UINT64_C + * + * If inttypes.h is is available, it will be pound-included in the + * configuration header. If it is not, the following macros will be defined if + * possible: + * + * PRId64 + * PRIu64 + * + * Availability of integer types is indicated by which of these are defined: + * + * HAS_INT8_T + * HAS_INT16_T + * HAS_INT32_T + * HAS_INT64_T + * + * If 64-bit integers are available, this macro will promote pointers to i64_t + * safely. + * + * PTR_TO_I64(ptr) + */ + +#ifndef H_CHAZ_INTEGERS +#define H_CHAZ_INTEGERS + +#include <stdio.h> + +/* Run the Integers module. + */ +void chaz_Integers_run(void); + +#endif /* H_CHAZ_INTEGERS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/LargeFiles.h" +/* Charmonizer/Probe/LargeFiles.h + */ + +#ifndef H_CHAZ_LARGE_FILES +#define H_CHAZ_LARGE_FILES + +#include <stdio.h> + +/* The LargeFiles module attempts to detect these symbols or alias them to + * synonyms: + * + * off64_t + * fopen64 + * ftello64 + * fseeko64 + * lseek64 + * pread64 + * + * If off64_t or its equivalent is available, this will be defined: + * + * HAS_64BIT_OFFSET_TYPE + * + * If 64-bit variants of fopen, ftell, and fseek are available, this will be + * defined: + * + * HAS_64BIT_STDIO + * + * If 64-bit variants of pread and lseek are available, then corresponding + * symbols will be defined: + * + * HAS_64BIT_PREAD + * HAS_64BIT_LSEEK + * + * Use of the off64_t symbol may require sys/types.h. + */ +void chaz_LargeFiles_run(void); + +#endif /* H_CHAZ_LARGE_FILES */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/Memory.h" +/* Charmonizer/Probe/Memory.h + */ + +#ifndef H_CHAZ_MEMORY +#define H_CHAZ_MEMORY + +/* The Memory module attempts to detect these symbols or alias them to + * synonyms: + * + * alloca + * + * These following symbols will be defined if the associated headers are + * available: + * + * HAS_SYS_MMAN_H <sys/mman.h> + * HAS_ALLOCA_H <alloca.h> + * HAS_MALLOC_H <malloc.h> + * + * Defined if alloca() is available via stdlib.h: + * + * ALLOCA_IN_STDLIB_H + */ +void chaz_Memory_run(void); + +#endif /* H_CHAZ_MEMORY */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/RegularExpressions.h" +/* Charmonizer/Probe/RegularExpressions.h -- regular expressions. + */ + +#ifndef H_CHAZ_REGULAREXPRESSIONS +#define H_CHAZ_REGULAREXPRESSIONS + +/* Run the RegularExpressions module. + */ +void chaz_RegularExpressions_run(void); + +#endif /* H_CHAZ_REGULAREXPRESSIONS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/Strings.h" +/* Charmonizer/Probe/Strings.h + */ + +#ifndef H_CHAZ_STRINGS +#define H_CHAZ_STRINGS + +/* The Strings module attempts to detect whether snprintf works as specified + * by the C99 standard. It also looks for system-specific functions which can + * be used to emulate snprintf. + */ +void chaz_Strings_run(void); + +#endif /* H_CHAZ_STRINGS */ + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/SymbolVisibility.h" +/* Charmonizer/Probe/SymbolVisibility.h + */ + +#ifndef H_CHAZ_SYMBOLVISIBILITY +#define H_CHAZ_SYMBOLVISIBILITY + +void chaz_SymbolVisibility_run(void); + +#endif /* H_CHAZ_SYMBOLVISIBILITY */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/UnusedVars.h" +/* Charmonizer/Probe/UnusedVars.h + */ + +#ifndef H_CHAZ_UNUSED_VARS +#define H_CHAZ_UNUSED_VARS + +#include <stdio.h> + +/* Run the UnusedVars module. + * + * These symbols are exported: + * + * UNUSED_VAR(var) + * UNREACHABLE_RETURN(type) + * + */ +void chaz_UnusedVars_run(void); + +#endif /* H_CHAZ_UNUSED_VARS */ + + + + +/***************************************************************************/ + +#line 21 "src/Charmonizer/Probe/VariadicMacros.h" +/* Charmonizer/Probe/VariadicMacros.h + */ + +#ifndef H_CHAZ_VARIADIC_MACROS +#define H_CHAZ_VARIADIC_MACROS + +#include <stdio.h> + +/* Run the VariadicMacros module. + * + * If your compiler supports ISO-style variadic macros, this will be defined: + * + * HAS_ISO_VARIADIC_MACROS + * + * If your compiler supports GNU-style variadic macros, this will be defined: + * + * HAS_GNUC_VARIADIC_MACROS + * + * If you have at least one of the above, this will be defined: + * + * HAS_VARIADIC_MACROS + */ +void chaz_VariadicMacros_run(void); + +#endif /* H_CHAZ_VARIADIC_MACROS */ + + + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/Library.c" +#include <string.h> +#include <stdlib.h> +/* #include "Charmonizer/Core/Library.h" */ +/* #include "Charmonizer/Core/Compiler.h" */ +/* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/OperatingSystem.h" */ + +struct chaz_Lib { + char *name; + char *version; + char *major_version; + int is_static; + int is_shared; + chaz_LibType lib_type; +}; + +static char* +S_build_filename(chaz_Lib *lib, const char *version, const char *ext); + +static const char* +S_get_prefix(void); + +chaz_Lib* +chaz_Lib_new(const char *name, chaz_LibType lib_type, const char *version, + const char *major_version) { + chaz_Lib *lib = (chaz_Lib*)malloc(sizeof(chaz_Lib)); + lib->name = chaz_Util_strdup(name); + lib->version = chaz_Util_strdup(version); + lib->major_version = chaz_Util_strdup(major_version); + lib->lib_type = lib_type; + if (lib_type == chaz_Lib_SHARED) { + lib->is_shared = 1; + lib->is_static = 0; + } + else if (lib_type == chaz_Lib_STATIC) { + lib->is_shared = 0; + lib->is_static = 1; + } + else { + chaz_Util_die("Invalid value for lib_type: %d", lib_type); + } + return lib; +} + +void +chaz_Lib_destroy(chaz_Lib *lib) { + free(lib->name); + free(lib->version); + free(lib->major_version); + free(lib); +} + +const char* +chaz_Lib_get_name(chaz_Lib *lib) { + return lib->name; +} + +const char* +chaz_Lib_get_version(chaz_Lib *lib) { + return lib->version; +} + +const char* +chaz_Lib_get_major_version(chaz_Lib *lib) { + return lib->major_version; +} + +int +chaz_Lib_is_shared (chaz_Lib *lib) { + return lib->is_shared; +} + +int +chaz_Lib_is_static (chaz_Lib *lib) { + return lib->is_static; +} + +char* +chaz_Lib_filename(chaz_Lib *lib) { + const char *ext = lib->is_shared + ? chaz_OS_shared_lib_ext() + : chaz_OS_static_lib_ext(); + + if ((strcmp(ext, ".dll") == 0) || strcmp(ext, ".lib") == 0) { + return S_build_filename(lib, lib->major_version, ext); + } + else { + return S_build_filename(lib, lib->version, ext); + } +} + +char* +chaz_Lib_major_version_filename(chaz_Lib *lib) { + const char *ext = lib->is_shared + ? chaz_OS_shared_lib_ext() + : chaz_OS_static_lib_ext(); + return S_build_filename(lib, lib->major_version, ext); +} + +char* +chaz_Lib_no_version_filename(chaz_Lib *lib) { + const char *prefix = S_get_prefix(); + const char *ext = lib->is_shared + ? chaz_OS_shared_lib_ext() + : chaz_OS_static_lib_ext(); + return chaz_Util_join("", prefix, lib->name, ext, NULL); +} + +char* +chaz_Lib_implib_filename(chaz_Lib *lib) { + return S_build_filename(lib, lib->major_version, ".lib"); +} + +char* +chaz_Lib_export_filename(chaz_Lib *lib) { + return S_build_filename(lib, lib->major_version, ".exp"); +} + +static char* +S_build_filename(chaz_Lib *lib, const char *version, const char *ext) { + const char *prefix = S_get_prefix(); + const char *shlib_ext = chaz_OS_shared_lib_ext(); + + /* Use `shlib_ext` as a proxy for OS to determine behavior, but append + * the supplied `ext`. */ + if (strcmp(shlib_ext, ".dll") == 0) { + return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL); + } + else if (strcmp(shlib_ext, ".dylib") == 0) { + return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL); + } + else { + return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL); + } +} + +static const char* +S_get_prefix() { + if (chaz_CC_msvc_version_num()) { + return ""; + } + else if (chaz_OS_is_cygwin()) { + return "cyg"; + } + else { + return "lib"; + } +} + + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/CFlags.c" +#include <string.h> +#include <stdlib.h> +/* #include "Charmonizer/Core/CFlags.h" */ +/* #include "Charmonizer/Core/Compiler.h" */ +/* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/OperatingSystem.h" */ +/* #include "Charmonizer/Core/Library.h" */ + +struct chaz_CFlags { + int style; + char *string; +}; + +chaz_CFlags* +chaz_CFlags_new(int style) { + chaz_CFlags *flags = (chaz_CFlags*)malloc(sizeof(chaz_CFlags)); + flags->style = style; + flags->string = chaz_Util_strdup(""); + return flags; +} + +void +chaz_CFlags_destroy(chaz_CFlags *flags) { + free(flags->string); + free(flags); +} + +const char* +chaz_CFlags_get_string(chaz_CFlags *flags) { + return flags->string; +} + +void +chaz_CFlags_append(chaz_CFlags *flags, const char *string) { + char *new_string; + if (flags->string[0] == '\0') { + new_string = chaz_Util_strdup(string); + } + else { + new_string = chaz_Util_join(" ", flags->string, string, NULL); + } + free(flags->string); + flags->string = new_string; +} + +void +chaz_CFlags_clear(chaz_CFlags *flags) { + if (flags->string[0] != '\0') { + free(flags->string); + flags->string = chaz_Util_strdup(""); + } +} + +void +chaz_CFlags_set_output_obj(chaz_CFlags *flags, const char *filename) { + const char *output; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + output = "/c /Fo"; + } + else { + /* POSIX */ + output = "-c -o "; + } + string = chaz_Util_join("", output, filename, NULL); + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_set_output_exe(chaz_CFlags *flags, const char *filename) { + const char *output; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + output = "/Fe"; + } + else { + /* POSIX */ + output = "-o "; + } + string = chaz_Util_join("", output, filename, NULL); + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_add_define(chaz_CFlags *flags, const char *name, + const char *value) { + const char *define; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + define = "/D"; + } + else { + /* POSIX */ + define = "-D "; + } + if (value) { + string = chaz_Util_join("", define, name, "=", value, NULL); + } + else { + string = chaz_Util_join("", define, name, NULL); + } + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_add_include_dir(chaz_CFlags *flags, const char *dir) { + const char *include; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + include = "/I "; + } + else { + /* POSIX */ + include = "-I "; + } + string = chaz_Util_join("", include, dir, NULL); + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_enable_optimization(chaz_CFlags *flags) { + const char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + string = "/O2"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + string = "-O2"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + string = "-xO4"; + } + else { + /* POSIX */ + string = "-O 1"; + } + chaz_CFlags_append(flags, string); +} + +void +chaz_CFlags_enable_debugging(chaz_CFlags *flags) { + if (flags->style == CHAZ_CFLAGS_STYLE_GNU + || flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + chaz_CFlags_append(flags, "-g"); + } +} + +void +chaz_CFlags_disable_strict_aliasing(chaz_CFlags *flags) { + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + return; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + chaz_CFlags_append(flags, "-fno-strict-aliasing"); + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + chaz_CFlags_append(flags, "-xalias_level=any"); + } + else { + chaz_Util_die("Don't know how to disable strict aliasing with '%s'", + chaz_CC_get_cc()); + } +} + +void +chaz_CFlags_set_warnings_as_errors(chaz_CFlags *flags) { + const char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + string = "/WX"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + string = "-Werror"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + string = "-errwarn=%all"; + } + else { + chaz_Util_die("Don't know how to set warnings as errors with '%s'", + chaz_CC_get_cc()); + } + chaz_CFlags_append(flags, string); +} + +void +chaz_CFlags_compile_shared_library(chaz_CFlags *flags) { + const char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + string = "/MD"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + const char *shlib_ext = chaz_OS_shared_lib_ext(); + if (strcmp(shlib_ext, ".dylib") == 0) { + string = "-fno-common"; + } + else if (strcmp(shlib_ext, ".so") == 0) { + string = "-fPIC"; + } + else if (strcmp(shlib_ext, ".dll") == 0) { + /* MinGW */ + return; + } + else { + /* unknown */ + return; + } + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + string = "-KPIC"; + } + else { + return; + } + chaz_CFlags_append(flags, string); +} + +void +chaz_CFlags_hide_symbols(chaz_CFlags *flags) { + if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + if (strcmp(chaz_OS_shared_lib_ext(), ".dll") != 0) { + chaz_CFlags_append(flags, "-fvisibility=hidden"); + } + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + if (chaz_CC_sun_c_version_num() >= 0x550) { + /* Sun Studio 8. */ + chaz_CFlags_append(flags, "-xldscope=hidden"); + } + } +} + +void +chaz_CFlags_link_shared_library(chaz_CFlags *flags) { + const char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + string = "/DLL"; + } + else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + if (strcmp(chaz_OS_shared_lib_ext(), ".dylib") == 0) { + string = "-dynamiclib"; + } + else { + string = "-shared"; + } + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + string = "-G"; + } + else { + chaz_Util_die("Don't know how to link a shared library with '%s'", + chaz_CC_get_cc()); + } + chaz_CFlags_append(flags, string); +} + +void +chaz_CFlags_set_shared_library_version(chaz_CFlags *flags, chaz_Lib *lib) { + if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + const char *shlib_ext = chaz_OS_shared_lib_ext(); + + if (strcmp(shlib_ext, ".dylib") == 0) { + const char *version = chaz_Lib_get_version(lib); + char *string + = chaz_Util_join(" ", "-current_version", version, NULL); + chaz_CFlags_append(flags, string); + free(string); + } + else if (strcmp(shlib_ext, ".so") == 0) { + char *soname = chaz_Lib_major_version_filename(lib); + char *string = chaz_Util_join("", "-Wl,-soname,", soname, NULL); + chaz_CFlags_append(flags, string); + free(string); + free(soname); + } + } + else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) { + char *soname = chaz_Lib_major_version_filename(lib); + char *string = chaz_Util_join(" ", "-h", soname, NULL); + chaz_CFlags_append(flags, string); + free(string); + free(soname); + } +} + +void +chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename) { + const char *output; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + output = "/OUT:"; + } + else { + output = "-o "; + } + string = chaz_Util_join("", output, filename, NULL); + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory) { + const char *lib_path; + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + if (strcmp(directory, ".") == 0) { + /* The MS linker searches the current directory by default. */ + return; + } + else { + lib_path = "/LIBPATH:"; + } + } + else { + lib_path = "-L "; + } + string = chaz_Util_join("", lib_path, directory, NULL); + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_add_library(chaz_CFlags *flags, chaz_Lib *lib) { + char *filename; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + filename = chaz_Lib_implib_filename(lib); + } + else { + filename = chaz_Lib_filename(lib); + } + chaz_CFlags_append(flags, filename); + free(filename); +} + +void +chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) { + char *string; + if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) { + string = chaz_Util_join("", library, ".lib", NULL); + } + else { + string = chaz_Util_join(" ", "-l", library, NULL); + } + chaz_CFlags_append(flags, string); + free(string); +} + +void +chaz_CFlags_enable_code_coverage(chaz_CFlags *flags) { + if (flags->style == CHAZ_CFLAGS_STYLE_GNU) { + chaz_CFlags_append(flags, "--coverage"); + } + else { + chaz_Util_die("Don't know how to enable code coverage with '%s'", + chaz_CC_get_cc()); + } +} + + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/CLI.c" +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +/* #include "Charmonizer/Core/CLI.h" */ +/* #include "Charmonizer/Core/Util.h" */ + +typedef struct chaz_CLIOption { + char *name; + char *help; + char *value; + int defined; + int flags; +} chaz_CLIOption; + +struct chaz_CLI { + char *name; + char *desc; + char *usage; + char *help; + chaz_CLIOption *opts; + int num_opts; +}; + +static void +S_chaz_CLI_error(chaz_CLI *self, const char *pattern, ...) { + va_list ap; + if (chaz_Util_verbosity > 0) { + va_start(ap, pattern); + vfprintf(stderr, pattern, ap); + va_end(ap); + fprintf(stderr, "\n"); + } +} + +static void +S_chaz_CLI_rebuild_help(chaz_CLI *self) { + int i; + size_t amount = 200; /* Length of section headers. */ + + /* Allocate space. */ + if (self->usage) { + amount += strlen(self->usage); + } + else { + amount += strlen(self->name); + } + if (self->desc) { + amount += strlen(self->desc); + } + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + amount += 24 + 2 * strlen(opt->name); + if (opt->flags) { + amount += strlen(opt->name); + } + if (opt->help) { + amount += strlen(opt->help); + } + } + free(self->help); + self->help = (char*)malloc(amount); + self->help[0] = '\0'; + + /* Accumulate "help" string. */ + if (self->usage) { + strcat(self->help, self->usage); + } + else { + strcat(self->help, "Usage: "); + strcat(self->help, self->name); + if (self->num_opts) { + strcat(self->help, " [OPTIONS]"); + } + } + if (self->desc) { + strcat(self->help, "\n\n"); + strcat(self->help, self->desc); + } + strcat(self->help, "\n"); + if (self->num_opts) { + strcat(self->help, "\nOptional arguments:\n"); + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + size_t line_start = strlen(self->help); + size_t current_len; + + strcat(self->help, " --"); + strcat(self->help, opt->name); + current_len = strlen(self->help); + if (opt->flags) { + int j; + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + self->help[current_len++] = '['; + } + self->help[current_len++] = '='; + for (j = 0; opt->name[j]; j++) { + self->help[current_len++] = toupper(opt->name[j]); + } + if (opt->flags & CHAZ_CLI_ARG_OPTIONAL) { + strcat(self->help, "]"); + } + self->help[current_len] = '\0'; + } + if (opt->help) { + self->help[current_len++] = ' '; + while (current_len - line_start < 25) { + self->help[current_len++] = ' '; + } + self->help[current_len] = '\0'; + strcpy(self->help + current_len, opt->help); + } + strcat(self->help, "\n"); + } + } + strcat(self->help, "\n"); +} + +chaz_CLI* +chaz_CLI_new(const char *name, const char *description) { + chaz_CLI *self = calloc(1, sizeof(chaz_CLI)); + self->name = chaz_Util_strdup(name ? name : "PROGRAM"); + self->desc = description ? chaz_Util_strdup(description) : NULL; + self->help = NULL; + self->opts = NULL; + self->num_opts = 0; + S_chaz_CLI_rebuild_help(self); + return self; +} + +void +chaz_CLI_destroy(chaz_CLI *self) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + free(opt->name); + free(opt->help); + free(opt->value); + } + free(self->name); + free(self->desc); + free(self->opts); + free(self->usage); + free(self->help); + free(self); +} + +void +chaz_CLI_set_usage(chaz_CLI *self, const char *usage) { + free(self->usage); + self->usage = chaz_Util_strdup(usage); +} + +const char* +chaz_CLI_help(chaz_CLI *self) { + return self->help; +} + +int +chaz_CLI_register(chaz_CLI *self, const char *name, const char *help, + int flags) { + int rank; + int i; + int arg_required = !!(flags & CHAZ_CLI_ARG_REQUIRED); + int arg_optional = !!(flags & CHAZ_CLI_ARG_OPTIONAL); + + /* Validate flags */ + if (arg_required && arg_optional) { + S_chaz_CLI_error(self, "Conflicting flags: value both optional " + "and required"); + return 0; + } + + /* Insert new option. Keep options sorted by name. */ + for (rank = self->num_opts; rank > 0; rank--) { + int comparison = strcmp(name, self->opts[rank - 1].name); + if (comparison == 0) { + S_chaz_CLI_error(self, "Option '%s' already registered", name); + return 0; + } + else if (comparison > 0) { + break; + } + } + self->num_opts += 1; + self->opts = realloc(self->opts, self->num_opts * sizeof(chaz_CLIOption)); + for (i = self->num_opts - 1; i > rank; i--) { + self->opts[i] = self->opts[i - 1]; + } + self->opts[rank].name = chaz_Util_strdup(name); + self->opts[rank].help = help ? chaz_Util_strdup(help) : NULL; + self->opts[rank].flags = flags; + self->opts[rank].defined = 0; + self->opts[rank].value = NULL; + + /* Update `help` with new option. */ + S_chaz_CLI_rebuild_help(self); + + return 1; +} + +int +chaz_CLI_set(chaz_CLI *self, const char *name, const char *value) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (opt->defined) { + S_chaz_CLI_error(self, "'%s' specified multiple times", name); + return 0; + } + opt->defined = 1; + if (value != NULL) { + opt->value = chaz_Util_strdup(value); + } + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to set unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_unset(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + free(opt->value); + opt->value = NULL; + opt->defined = 0; + return 1; + } + } + S_chaz_CLI_error(self, "Attempt to unset unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_defined(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->defined; + } + } + S_chaz_CLI_error(self, "Inquiry for unknown option: '%s'", name); + return 0; +} + +long +chaz_CLI_longval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + if (!opt->defined || !opt->value) { + return 0; + } + return strtol(opt->value, NULL, 10); + } + } + S_chaz_CLI_error(self, "Longval request for unknown option: '%s'", name); + return 0; +} + +const char* +chaz_CLI_strval(chaz_CLI *self, const char *name) { + int i; + for (i = 0; i < self->num_opts; i++) { + chaz_CLIOption *opt = &self->opts[i]; + if (strcmp(opt->name, name) == 0) { + return opt->value; + } + } + S_chaz_CLI_error(self, "Strval request for unknown option: '%s'", name); + return 0; +} + +int +chaz_CLI_parse(chaz_CLI *self, int argc, const char *argv[]) { + int i; + char *name = NULL; + size_t name_cap = 0; + + /* Parse most args. */ + for (i = 1; i < argc; i++) { + const char *arg = argv[i]; + size_t name_len = 0; + int has_equals = 0; + const char *value = NULL; + + /* Stop processing if we see `-` or `--`. */ + if (strcmp(arg, "--") == 0 || strcmp(arg, "-") == 0) { + break; + } + + if (strncmp(arg, "--", 2) != 0) { + S_chaz_CLI_error(self, "Unexpected argument: '%s'", arg); + free(name); + return 0; + } + + /* Extract the name of the argument, look for a potential value. */ + while (1) { + char c = arg[name_len + 2]; + if (isalnum(c) || c == '-' || c == '_') { + name_len++; + } + else if (c == '\0') { + break; + } + else if (c == '=') { + /* The rest of the arg is the value. */ + value = arg + 2 + name_len + 1; + break; + } + else { + free(name); + S_chaz_CLI_error(self, "Malformed argument: '%s'", arg); + return 0; + } + } + if (name_len + 1 > name_cap) { + name_cap = name_len + 1; + name = (char*)realloc(name, name_cap); + } + memcpy(name, arg + 2, name_len); + name[name_len] = '\0'; + + /* Attempt to set the option. */ + if (!chaz_CLI_set(self, name, value)) { + free(name); + return 0; + } + } + + free(name); + return 1; +} + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/Compiler.c" +#include <string.h> +#include <stdlib.h> +/* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/Compiler.h" */ +/* #include "Charmonizer/Core/ConfWriter.h" */ +/* #include "Charmonizer/Core/OperatingSystem.h" */ + +/* Detect macros which may help to identify some compilers. + */ +static void +chaz_CC_detect_known_compilers(void); + +/* Temporary files. */ +#define CHAZ_CC_TRY_SOURCE_PATH "_charmonizer_try.c" +#define CHAZ_CC_TRY_BASENAME "_charmonizer_try" +#define CHAZ_CC_TARGET_PATH "_charmonizer_target" + +/* Static vars. */ +static struct { + char *cc_command; + char *cflags; + char *try_exe_name; + char obj_ext[10]; + char gcc_version_str[30]; + int cflags_style; + int intval___GNUC__; + int intval___GNUC_MINOR__; + int intval___GNUC_PATCHLEVEL__; + int intval__MSC_VER; + int intval___clang__; + int intval___SUNPRO_C; + chaz_CFlags *extra_cflags; + chaz_CFlags *temp_cflags; +} chaz_CC = { + NULL, NULL, NULL, + "", "", + 0, 0, 0, 0, 0, 0, 0, + NULL, NULL +}; + +void +chaz_CC_init(const char *compiler_command, const char *compiler_flags) { + const char *code = "int main() { return 0; }\n"; + int compile_succeeded = 0; + + if (chaz_Util_verbosity) { printf("Creating compiler object...\n"); } + + /* Assign, init. */ + chaz_CC.cc_command = chaz_Util_strdup(compiler_command); + chaz_CC.cflags = chaz_Util_strdup(compiler_flags); + chaz_CC.extra_cflags = NULL; + chaz_CC.temp_cflags = NULL; + + /* Set names for the targets which we "try" to compile. */ + chaz_CC.try_exe_name + = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_OS_exe_ext(), NULL); + + /* If we can't compile anything, game over. */ + if (chaz_Util_verbosity) { + printf("Trying to compile a small test file...\n"); + } + /* Try MSVC argument style. */ + strcpy(chaz_CC.obj_ext, ".obj"); + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC; + compile_succeeded = chaz_CC_test_compile(code); + if (!compile_succeeded) { + /* Try POSIX argument style. */ + strcpy(chaz_CC.obj_ext, ".o"); + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_POSIX; + compile_succeeded = chaz_CC_test_compile(code); + } + if (!compile_succeeded) { + chaz_Util_die("Failed to compile a small test file"); + } + + chaz_CC_detect_known_compilers(); + + if (chaz_CC.intval___GNUC__) { + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_GNU; + } + else if (chaz_CC.intval__MSC_VER) { + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_MSVC; + } + else if (chaz_CC.intval___SUNPRO_C) { + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_SUN_C; + } + else { + chaz_CC.cflags_style = CHAZ_CFLAGS_STYLE_POSIX; + } + chaz_CC.extra_cflags = chaz_CFlags_new(chaz_CC.cflags_style); + chaz_CC.temp_cflags = chaz_CFlags_new(chaz_CC.cflags_style); +} + +static const char chaz_CC_detect_macro_code[] = + CHAZ_QUOTE( #include <stdio.h> ) + CHAZ_QUOTE( int main() { ) + CHAZ_QUOTE( #ifndef %s ) + CHAZ_QUOTE( #error "nope" ) + CHAZ_QUOTE( #endif ) + CHAZ_QUOTE( printf("%%d", %s); ) + CHAZ_QUOTE( return 0; ) + CHAZ_QUOTE( } ); + +static int +chaz_CC_detect_macro(const char *macro) { + size_t size = sizeof(chaz_CC_detect_macro_code) + + (strlen(macro) * 2) + + 20; + char *code = (char*)malloc(size); + int retval = 0; + char *output; + size_t len; + sprintf(code, chaz_CC_detect_macro_code, macro, macro); + output = chaz_CC_capture_output(code, &len); + if (output) { + retval = atoi(output); + free(output); + } + free(code); + return retval; +} + +static void +chaz_CC_detect_known_compilers(void) { + chaz_CC.intval___GNUC__ = chaz_CC_detect_macro("__GNUC__"); + if (chaz_CC.intval___GNUC__) { + chaz_CC.intval___GNUC_MINOR__ + = chaz_CC_detect_macro("__GNUC_MINOR__"); + chaz_CC.intval___GNUC_PATCHLEVEL__ + = chaz_CC_detect_macro("__GNUC_PATCHLEVEL__"); + sprintf(chaz_CC.gcc_version_str, "%d.%d.%d", chaz_CC.intval___GNUC__, + chaz_CC.intval___GNUC_MINOR__, + chaz_CC.intval___GNUC_PATCHLEVEL__); + } + chaz_CC.intval__MSC_VER = chaz_CC_detect_macro("_MSC_VER"); + chaz_CC.intval___clang__ = chaz_CC_detect_macro("__clang__"); + chaz_CC.intval___SUNPRO_C = chaz_CC_detect_macro("__SUNPRO_C"); +} + +void +chaz_CC_clean_up(void) { + free(chaz_CC.cc_command); + free(chaz_CC.cflags); + free(chaz_CC.try_exe_name); + chaz_CFlags_destroy(chaz_CC.extra_cflags); + chaz_CFlags_destroy(chaz_CC.temp_cflags); +} + +int +chaz_CC_compile_exe(const char *source_path, const char *exe_name, + const char *code) { + chaz_CFlags *local_cflags = chaz_CFlags_new(chaz_CC.cflags_style); + const char *extra_cflags_string = ""; + const char *temp_cflags_string = ""; + const char *local_cflags_string; + char *exe_file = chaz_Util_join("", exe_name, chaz_OS_exe_ext(), NULL); + char *command; + int result; + + /* Write the source file. */ + chaz_Util_write_file(source_path, code); + + /* Prepare and run the compiler command. */ + if (chaz_CC.extra_cflags) { + extra_cflags_string = chaz_CFlags_get_string(chaz_CC.extra_cflags); + } + if (chaz_CC.temp_cflags) { + temp_cflags_string = chaz_CFlags_get_string(chaz_CC.temp_cflags); + } + chaz_CFlags_set_output_exe(local_cflags, exe_file); + local_cflags_string = chaz_CFlags_get_string(local_cflags); + command = chaz_Util_join(" ", chaz_CC.cc_command, chaz_CC.cflags, + source_path, extra_cflags_string, + temp_cflags_string, local_cflags_string, NULL); + if (chaz_Util_verbosity < 2) { + chaz_OS_run_quietly(command); + } + else { + system(command); + } + + if (chaz_CC.intval__MSC_VER) { + /* Zap MSVC junk. */ + size_t junk_buf_size = strlen(exe_file) + 4; + char *junk = (char*)malloc(junk_buf_size); + sprintf(junk, "%s.obj", exe_name); + chaz_Util_remove_and_verify(junk); + sprintf(junk, "%s.ilk", exe_name); + chaz_Util_remove_and_verify(junk); + sprintf(junk, "%s.pdb", exe_name); + chaz_Util_remove_and_verify(junk); + free(junk); + } + + /* See if compilation was successful. Remove the source file. */ + result = chaz_Util_can_open_file(exe_file); + if (!chaz_Util_remove_and_verify(source_path)) { + chaz_Util_die("Failed to remove '%s'", source_path); + } + + chaz_CFlags_destroy(local_cflags); + free(command); + free(exe_file); + return result; +} + +int +chaz_CC_compile_obj(const char *source_path, const char *obj_name, + const char *code) { + chaz_CFlags *local_cflags = chaz_CFlags_new(chaz_CC.cflags_style); + const char *extra_cflags_string = ""; + const char *temp_cflags_string = ""; + const char *local_cflags_string; + char *obj_file = chaz_Util_join("", obj_name, chaz_CC.obj_ext, NULL); + char *command; + int result; + + /* Write the source file. */ + chaz_Util_write_file(source_path, code); + + /* Prepare and run the compiler command. */ + if (chaz_CC.extra_cflags) { + extra_cflags_string = chaz_CFlags_get_string(chaz_CC.extra_cflags); + } + if (chaz_CC.temp_cflags) { + temp_cflags_string = chaz_CFlags_get_string(chaz_CC.temp_cflags); + } + chaz_CFlags_set_output_obj(local_cflags, obj_file); + local_cflags_string = chaz_CFlags_get_string(local_cflags); + command = chaz_Util_join(" ", chaz_CC.cc_command, chaz_CC.cflags, + source_path, extra_cflags_string, + temp_cflags_string, local_cflags_string, NULL); + if (chaz_Util_verbosity < 2) { + chaz_OS_run_quietly(command); + } + else { + system(command); + } + + /* See if compilation was successful. Remove the source file. */ + result = chaz_Util_can_open_file(obj_file); + if (!chaz_Util_remove_and_verify(source_path)) { + chaz_Util_die("Failed to remove '%s'", source_path); + } + + chaz_CFlags_destroy(local_cflags); + free(command); + free(obj_file); + return result; +} + +int +chaz_CC_test_compile(const char *source) { + int compile_succeeded; + char *try_obj_name + = chaz_Util_join("", CHAZ_CC_TRY_BASENAME, chaz_CC.obj_ext, NULL); + if (!chaz_Util_remove_and_verify(try_obj_name)) { + chaz_Util_die("Failed to delete file '%s'", try_obj_name); + } + compile_succeeded = chaz_CC_compile_obj(CHAZ_CC_TRY_SOURCE_PATH, + CHAZ_CC_TRY_BASENAME, source); + chaz_Util_remove_and_verify(try_obj_name); + free(try_obj_name); + return compile_succeeded; +} + +char* +chaz_CC_capture_output(const char *source, size_t *output_len) { + char *captured_output = NULL; + int compile_succeeded; + + /* Clear out previous versions and test to make sure removal worked. */ + if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) { + chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name); + } + if (!chaz_Util_remove_and_verify(CHAZ_CC_TARGET_PATH)) { + chaz_Util_die("Failed to delete file '%s'", CHAZ_CC_TARGET_PATH); + } + + /* Attempt compilation; if successful, run app and slurp output. */ + compile_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH, + CHAZ_CC_TRY_BASENAME, source); + if (compile_succeeded) { + chaz_OS_run_local_redirected(chaz_CC.try_exe_name, + CHAZ_CC_TARGET_PATH); + captured_output = chaz_Util_slurp_file(CHAZ_CC_TARGET_PATH, + output_len); + } + else { + *output_len = 0; + } + + /* Remove all the files we just created. */ + chaz_Util_remove_and_verify(CHAZ_CC_TRY_SOURCE_PATH); + chaz_Util_remove_and_verify(chaz_CC.try_exe_name); + chaz_Util_remove_and_verify(CHAZ_CC_TARGET_PATH); + + return captured_output; +} + +const char* +chaz_CC_get_cc(void) { + return chaz_CC.cc_command; +} + +const char* +chaz_CC_get_cflags(void) { + return chaz_CC.cflags; +} + +chaz_CFlags* +chaz_CC_get_extra_cflags(void) { + return chaz_CC.extra_cflags; +} + +chaz_CFlags* +chaz_CC_get_temp_cflags(void) { + return chaz_CC.temp_cflags; +} + +chaz_CFlags* +chaz_CC_new_cflags(void) { + return chaz_CFlags_new(chaz_CC.cflags_style); +} + +const char* +chaz_CC_obj_ext(void) { + return chaz_CC.obj_ext; +} + +int +chaz_CC_gcc_version_num(void) { + return 10000 * chaz_CC.intval___GNUC__ + + 100 * chaz_CC.intval___GNUC_MINOR__ + + chaz_CC.intval___GNUC_PATCHLEVEL__; +} + +const char* +chaz_CC_gcc_version(void) { + return chaz_CC.intval___GNUC__ ? chaz_CC.gcc_version_str : NULL; +} + +int +chaz_CC_msvc_version_num(void) { + return chaz_CC.intval__MSC_VER; +} + +int +chaz_CC_sun_c_version_num(void) { + return chaz_CC.intval___SUNPRO_C; +} + +const char* +chaz_CC_link_command() { + if (chaz_CC.intval__MSC_VER) { + return "link"; + } + else { + return chaz_CC.cc_command; + } +} + +char* +chaz_CC_format_archiver_command(const char *target, const char *objects) { + if (chaz_CC.intval__MSC_VER) { + /* TODO: Write `objects` to a temporary file in order to avoid + * exceeding line length limits. */ + char *out = chaz_Util_join("", "/OUT:", target, NULL); + char *command = chaz_Util_join(" ", "lib", "/NOLOGO", out, NULL); + free(out); + return command; + } + else { + return chaz_Util_join(" ", "ar", "rcs", target, objects, NULL); + } +} + +char* +chaz_CC_format_ranlib_command(const char *target) { + if (chaz_CC.intval__MSC_VER) { + return NULL; + } + return chaz_Util_join(" ", "ranlib", target, NULL); +} + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/ConfWriter.c" +/* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/ConfWriter.h" */ +#include <stdarg.h> +#include <stdio.h> + +#define CW_MAX_WRITERS 10 +static struct { + chaz_ConfWriter *writers[CW_MAX_WRITERS]; + size_t num_writers; +} chaz_CW; + +void +chaz_ConfWriter_init(void) { + chaz_CW.num_writers = 0; + return; +} + +void +chaz_ConfWriter_clean_up(void) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->clean_up(); + } +} + +void +chaz_ConfWriter_append_conf(const char *fmt, ...) { + va_list args; + size_t i; + + for (i = 0; i < chaz_CW.num_writers; i++) { + va_start(args, fmt); + chaz_CW.writers[i]->vappend_conf(fmt, args); + va_end(args); + } +} + +void +chaz_ConfWriter_add_def(const char *sym, const char *value) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_def(sym, value); + } +} + +void +chaz_ConfWriter_add_global_def(const char *sym, const char *value) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_global_def(sym, value); + } +} + +void +chaz_ConfWriter_add_typedef(const char *type, const char *alias) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_typedef(type, alias); + } +} + +void +chaz_ConfWriter_add_global_typedef(const char *type, const char *alias) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_global_typedef(type, alias); + } +} + +void +chaz_ConfWriter_add_sys_include(const char *header) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_sys_include(header); + } +} + +void +chaz_ConfWriter_add_local_include(const char *header) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->add_local_include(header); + } +} + +void +chaz_ConfWriter_start_module(const char *module_name) { + size_t i; + if (chaz_Util_verbosity > 0) { + printf("Running %s module...\n", module_name); + } + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->start_module(module_name); + } +} + +void +chaz_ConfWriter_end_module(void) { + size_t i; + for (i = 0; i < chaz_CW.num_writers; i++) { + chaz_CW.writers[i]->end_module(); + } +} + +void +chaz_ConfWriter_add_writer(chaz_ConfWriter *writer) { + chaz_CW.writers[chaz_CW.num_writers] = writer; + chaz_CW.num_writers++; +} + + +/***************************************************************************/ + +#line 17 "src/Charmonizer/Core/ConfWriterC.c" +/* #include "Charmonizer/Core/Util.h" */ +/* #include "Charmonizer/Core/ConfWriter.h" */ +/* #include "Charmonizer/Core/ConfWriterC.h" */ +/* #include "Charmonizer/Core/OperatingSystem.h" */ +/* #include "Charmonizer/Core/Compiler.h" */ +#include <ctype.h> +#include <errno.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef enum chaz_ConfElemType { + CHAZ_CONFELEM_DEF, + CHAZ_CONFELEM_GLOBAL_DEF, + CHAZ_CONFELEM_TYPEDEF, + CHAZ_CONFELEM_GLOBAL_TYPEDEF, + CHAZ_CONFELEM_SYS_INCLUDE, + CHAZ_CONFELEM_LOCAL_INCLUDE +} chaz_ConfElemType; + +typedef struct chaz_ConfElem { + char *str1; + char *str2; + chaz_ConfElemType type; +} chaz_ConfElem; + +/* Static vars. */ +static struct { + FILE *fh; + char *MODULE_NAME; + chaz_ConfElem *defs; + size_t def_cap; + size_t def_count; +} chaz_ConfWriterC = { NULL, NULL, 0, 0 }; +static chaz_ConfWriter CWC_conf_writer; + +/* Open the charmony.h file handle. Print supplied text to it, if non-null. + * Print an explanatory comment and open the include guard. + */ +static void +chaz_ConfWriterC_open_charmony_h(const char *charmony_start); + +/* Push a new elem onto the def list. */ +static void +chaz_ConfWriterC_push_def_list_item(const char *str1, const char *str2, + chaz_ConfElemType type); + +/* Free the def list. */ +static void +chaz_ConfWriterC_clear_def_list(void); + +static void +chaz_ConfWriterC_clean_up(void); +static void +chaz_ConfWriterC_vappend_conf(const char *fmt, va_list args); +static void +chaz_ConfWriterC_add_def(const char *sym, const char *value); +static void +chaz_ConfWriterC_add_global_def(const char *sym, const char *value); +static void +chaz_ConfWriterC_add_typedef(const char *type, const char *alias); +static void +chaz_ConfWriterC_add_global_typedef(const char *type, const char *alias); +static void +chaz_ConfWriterC_add_sys_include(const char *header); +static void +chaz_ConfWriterC_add_local_include(const char *header); +static void +chaz_ConfWriterC_start_module(const char *module_name); +static void +chaz_ConfWriterC_end_module(void); + +void +chaz_ConfWriterC_enable(void) { + CWC_conf_writer.clean_up = chaz_ConfWriterC_clean_up; + CWC_conf_writer.vappend_conf = chaz_ConfWriterC_vappend_conf; + CWC_conf_writer.add_def = chaz_ConfWriterC_add_def; + CWC_conf_writer.add_global_def = chaz_ConfWriterC_add_global_def; + CWC_conf_writer.add_typedef = chaz_ConfWriterC_add_typedef; + CWC_conf_writer.add_global_typedef = chaz_ConfWriterC_add_global_typedef; + CWC_conf_writer.add_sys_include = chaz_ConfWriterC_add_sys_include; + CWC_conf_writer.add_local_include = chaz_ConfWriterC_add_local_include; + CWC_conf_writer.start_module = chaz_ConfWriterC_start_module; + CWC_conf_writer.end_module = chaz_ConfWriterC_end_module; + chaz_ConfWriterC_open_charmony_h(NULL); + chaz_ConfWriter_add_writer(&CWC_conf_writer); + return; +} + +static void +chaz_ConfWriterC_open_charmony_h(const char *charmony_start) { + /* Open the filehandle. */ + chaz_ConfWriterC.fh = fopen("charmony.h", "w+"); + if (chaz_ConfWriterC.fh == NULL) { + chaz_Util_die("Can't open 'charmony.h': %s", strerror(errno)); + } + + /* Print supplied text (if any) along with warning, open include guard. */ + if (charmony_start != NULL) { + fwrite(charmony_start, sizeof(char), strlen(charmony_start), + chaz_ConfWriterC.fh); + } + fprintf(chaz_ConfWriterC.fh, + "/* Header file auto-generated by Charmonizer. \n" + " * DO NOT EDIT THIS FILE!!\n" + " */\n\n" + "#ifndef H_CHARMONY\n" + "#define H_CHARMONY 1\n\n" + ); +} + +static void +chaz_ConfWriterC_clean_up(void) { + /* Write the last bit of charmony.h and close. */ + fprintf(chaz_ConfWriterC.fh, "#endif /* H_CHARMONY */\n\n"); + if (fclose(chaz_ConfWriterC.fh)) { + chaz_Util_die("Couldn't close 'charmony.h': %s", strerror(errno)); + } +} + +static void +chaz_ConfWriterC_vappend_conf(const char *fmt, va_list args) { + vfprintf(chaz_ConfWriterC.fh, fmt, args); +} + +static int +chaz_ConfWriterC_sym_is_uppercase(const char *sym) { + return isupper(sym[0]); +} + +static char* +chaz_ConfWriterC_uppercase_string(const char *src) { + char *retval = chaz_Util_strdup(src); + size_t i; + for (i = 0; retval[i]; ++i) { + retval[i] = toupper(retval[i]); + } + return retval; +} + +static void +chaz_ConfWriterC_add_def(const char *sym, const char *value) { + chaz_ConfWriterC_push_def_list_item(sym, value, CHAZ_CONFELEM_DEF); +} + +static void +chaz_ConfWriterC_append_def_to_conf(const char *sym, const char *value) { + if (value) { + if (chaz_ConfWriterC_sym_is_uppercase(sym)) { + fprintf(chaz_ConfWriterC.fh, "#define CHY_%s %s\n", sym, value); + } + else { + fprintf(chaz_ConfWriterC.fh, "#define chy_%s %s\n", sym, value); + } + } + else { + if (chaz_ConfWriterC_sym_is_uppercase(sym)) { + fprintf(chaz_ConfWriterC.fh, "#define CHY_%s\n", sym); + } + else { + fprintf(chaz_ConfWriterC.fh, "#define chy_%s\n", sym); + } + } +} + +static void +chaz_ConfWriterC_add_global_def(const char *sym, const char *value) { + chaz_ConfWriterC_push_def_list_item(sym, value, CHAZ_CONFELEM_GLOBAL_DEF); +} + +static void +chaz_ConfWriterC_append_global_def_to_conf(const char *sym, + const char *value) { + char *name_end = strchr(sym, '('); + if (name_end == NULL) { + if (strcmp(sym, value) == 0) { return; } + fprintf(chaz_ConfWriterC.fh, "#ifndef %s\n", sym); + } + else { + size_t name_len = (size_t)(name_end - sym); + char *name = chaz_Util_strdup(sym); + name[name_len] = '\0'; + fprintf(chaz_ConfWriterC.fh, "#ifndef %s\n", name); + free(name); + } + if (value) { + fprintf(chaz_ConfWriterC.fh, " #define %s %s\n", sym, value); + } + else { + fprintf(chaz_ConfWriterC.fh, " #define %s\n", sym); + } + fprintf(chaz_ConfWriterC.fh, "#endif\n"); +} + +static void +chaz_ConfWriterC_add_typedef(const char *type, const char *alias) { + chaz_ConfWriterC_push_def_list_item(alias, type, CHAZ_CONFELEM_TYPEDEF); +} + +static void +chaz_ConfWriterC_append_typedef_to_conf(const char *type, const char *alias) { + if (chaz_ConfWriterC_sym_is_uppercase(alias)) { + fprintf(chaz_ConfWriterC.fh, "typedef %s CHY_%s;\n", type, alias); + } + else { + fprintf(chaz_ConfWriterC.fh, "typedef %s chy_%s;\n", type, alias); + } +} + +static void +chaz_ConfWriterC_add_global_typedef(const char *type, const char *alias) { + chaz_ConfWriterC_push_def_list_item(alias, type, + CHAZ_CONFELEM_GLOBAL_TYPEDEF); +} + +static void +chaz_ConfWriterC_append_global_typedef_to_conf(const char *type, + const char *alias) { + if (strcmp(type, alias) == 0) { return; } + fprintf(chaz_ConfWriterC.fh, "typedef %s %s;\n", type, alias); +} + +static void +chaz_ConfWriterC_add_sys_include(const char *header) { + chaz_ConfWriterC_push_def_list_item(header, NULL, + CHAZ_CONFELEM_SYS_INCLUDE); +} + +static void +chaz_ConfWriterC_append_sys_include_to_conf(const char *header) { + fprintf(chaz_ConfWriterC.fh, "#include <%s>\n", header); +} + +static void +chaz_ConfWriterC_add_local_include(const char *header) { + chaz_ConfWriterC_push_def_list_item(header, NULL, + CHAZ_CONFELEM_LOCAL_INCLUDE); +} + +static void +chaz_ConfWriterC_append_local_include_to_conf(const char *header) { + fprintf(chaz_ConfWriterC.fh, "#include \"%s\"\n", header); +} + +static void +chaz_ConfWriterC_start_module(const char *module_name) { + fprintf(chaz_ConfWriterC.fh, "\n/* %s */\n", module_name); + chaz_ConfWriterC.MODULE_NAME + = chaz_ConfWriterC_uppercase_string(module_name); +} + +static void +chaz_ConfWriterC_end_module(void) { + size_t num_globals = 0; + size_t i; + chaz_ConfElem *defs = chaz_ConfWriterC.defs; + for (i = 0; i < chaz_ConfWriterC.def_count; i++) { + switch (defs[i].type) { + case CHAZ_CONFELEM_GLOBAL_DEF: + ++num_globals; + /* fall through */ + case CHAZ_CONFELEM_DEF: + chaz_ConfWriterC_append_def_to_conf(defs[i].str1, + defs[i].str2); + break; + case CHAZ_CONFELEM_GLOBAL_TYPEDEF: { + char *sym = chaz_ConfWriterC_uppercase_string(defs[i].str1); + chaz_ConfWriterC_append_def_to_conf(sym, defs[i].str2); + free(sym); + ++num_globals; + } + /* fall through */ + case CHAZ_CONFELEM_TYPEDEF: + chaz_ConfWriterC_append_typedef_to_conf(defs[i].str2, + defs[i].str1); + break; + case CHAZ_CONFELEM_SYS_INCLUDE: + ++num_globals; + break; + case CHAZ_CONFELEM_LOCAL_INCLUDE: + chaz_ConfWriterC_append_local_include_to_conf(defs[i].str1); + break; + default: + chaz_Util_die("Internal error: bad element type %d", + (int)defs[i].type); + } + } + + /* Write out short names. */ + fprintf(chaz_ConfWriterC.fh,
<TRUNCATED>
