blob: f34671443204d8b046136fdcf6b6eedf25cfa0d8 [file] [log] [blame]
/* 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);
}
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;
}
}
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,
"\n#if defined(CHY_USE_SHORT_NAMES) "
"|| defined(CHAZ_USE_SHORT_NAMES)\n"
);
for (i = 0; i < chaz_ConfWriterC.def_count; i++) {
switch (defs[i].type) {
case CHAZ_CONFELEM_DEF:
case CHAZ_CONFELEM_TYPEDEF:
{
const char *sym = defs[i].str1;
const char *value = defs[i].str2;
if (!value || strcmp(sym, value) != 0) {
const char *prefix
= chaz_ConfWriterC_sym_is_uppercase(sym)
? "CHY_" : "chy_";
fprintf(chaz_ConfWriterC.fh, " #define %s %s%s\n",
sym, prefix, sym);
}
}
break;
case CHAZ_CONFELEM_GLOBAL_DEF:
case CHAZ_CONFELEM_GLOBAL_TYPEDEF:
case CHAZ_CONFELEM_SYS_INCLUDE:
case CHAZ_CONFELEM_LOCAL_INCLUDE:
/* no-op */
break;
default:
chaz_Util_die("Internal error: bad element type %d",
(int)defs[i].type);
}
}
fprintf(chaz_ConfWriterC.fh, "#endif /* USE_SHORT_NAMES */\n");
/* Write out global definitions and system includes. */
if (num_globals) {
fprintf(chaz_ConfWriterC.fh, "\n#ifdef CHY_EMPLOY_%s\n\n",
chaz_ConfWriterC.MODULE_NAME);
for (i = 0; i < chaz_ConfWriterC.def_count; i++) {
switch (defs[i].type) {
case CHAZ_CONFELEM_GLOBAL_DEF:
chaz_ConfWriterC_append_global_def_to_conf(defs[i].str1,
defs[i].str2);
break;
case CHAZ_CONFELEM_GLOBAL_TYPEDEF:
chaz_ConfWriterC_append_global_typedef_to_conf(
defs[i].str2, defs[i].str1);
break;
case CHAZ_CONFELEM_SYS_INCLUDE:
chaz_ConfWriterC_append_sys_include_to_conf(defs[i].str1);
break;
case CHAZ_CONFELEM_DEF:
case CHAZ_CONFELEM_TYPEDEF:
case CHAZ_CONFELEM_LOCAL_INCLUDE:
/* no-op */
break;
default:
chaz_Util_die("Internal error: bad element type %d",
(int)defs[i].type);
}
}
fprintf(chaz_ConfWriterC.fh, "\n#endif /* EMPLOY_%s */\n",
chaz_ConfWriterC.MODULE_NAME);
}
fprintf(chaz_ConfWriterC.fh, "\n");