#define CHAZ_USE_SHORT_NAMES #include "Charmonizer/Core/Util.h" #include "Charmonizer/Core/ModHandler.h" #include "Charmonizer/Core/OperSys.h" #include "Charmonizer/Core/Compiler.h" #include #include #include #include /* Write the "_charm.h" file used by every probe. */ static void write_charm_h(); /* Compile a small wrapper application which is used to redirect error output * to devnull. */ static void build_charm_run(); /* Clean up the files associated with capture_output(). */ static void clean_up_try(); /* global vars */ struct chaz_OperSys *chaz_ModHand_os = NULL; struct chaz_Compiler *chaz_ModHand_compiler = NULL; chaz_bool_t chaz_ModHand_charm_run_available = false; FILE* chaz_ModHand_charmony_fh = NULL; /* static vars */ static char *try_app_path = NULL; static char *try_app_command = NULL; void chaz_ModHand_init() { /* set the name of the application which we "try" to execute */ (void)join_strings(&try_app_path, 0, TRY_APP_BASENAME, os->exe_ext, NULL); /* set the invocation string for the "try" application */ (void)join_strings(&try_app_command, 0, os->local_command_start, try_app_path, NULL); /* write files needed by this module and others */ build_charm_run(); write_charm_h(); } void chaz_ModHand_open_charmony_h(const char *charmony_start) { /* open the filehandle */ charmony_fh = fopen("charmony.h", "w+"); if (charmony_fh == NULL) die("Can't open 'charmony.h': %s", strerror(errno)); /* print supplied text (if any) along with warning, open include guard */ if (charmony_start != NULL) fprintf(charmony_fh, charmony_start); fprintf(charmony_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" ); } void chaz_ModHand_clean_up(void) { /* clean up some temp files */ remove("_charm.h"); os->remove_exe(os, "_charm_run"); os->remove_exe(os, "_charm_stat"); /* write the last bit of charmony.h and close */ fprintf(charmony_fh, "#endif /* H_CHARMONY */\n\n"); if (fclose(charmony_fh)) die("Couldn't close 'charmony.h': %s", strerror(errno)); } static char charm_h_code[] = METAQUOTE #ifndef CHARM_H #define CHARM_H 1 #include #define Charm_Setup \ freopen("_charmonizer_target", "w", stdout) #endif METAQUOTE; static void write_charm_h() { write_file("_charm.h", charm_h_code, strlen(charm_h_code)); } static char charm_run_code_a[] = METAQUOTE #include #include #include #include int main(int argc, char **argv) { char *command; size_t command_len = 1; /* terminating null */ int i; int retval; /* rebuild the command line args, minus the name of this utility */ for (i = 1; i < argc; i++) { command_len += strlen(argv[i]) + 1; } command = (char*)calloc(command_len, sizeof(char)); METAQUOTE; static char charm_run_code_b[] = METAQUOTE if (command == NULL) { fprintf(stderr, "calloc failed\n"); exit(1); } for (i = 1; i < argc; i++) { strcat( strcat(command, " "), argv[i] ); } /* redirect stdout and stderr to /dev/null or equivalent */ freopen( METAQUOTE; static char charm_run_code_c[] = METAQUOTE , "w", stdout); freopen( METAQUOTE; static char charm_run_code_d[] = METAQUOTE , "w", stderr); /* run the commmand and return its value to the parent process */ retval = system(command); free(command); return retval; } METAQUOTE; static void build_charm_run() { char *code = NULL; chaz_bool_t compile_succeeded = false; (void)join_strings(&code, 0, charm_run_code_a, charm_run_code_b, " \"", os->devnull, "\" ", charm_run_code_c, " \"", os->devnull, "\" ", charm_run_code_d, NULL); compile_succeeded = compiler->compile_exe(compiler, "_charm_run.c", "_charm_run", code, strlen(code)); if (!compile_succeeded) die("failed to compile _charm_run helper utility"); remove("_charm_run.c"); free(code); charm_run_available = true; } chaz_bool_t chaz_ModHand_test_compile(char *source, size_t source_len) { chaz_bool_t compile_succeeded; if ( !remove_and_verify(try_app_path) ) die("Failed to delete file '%s'", try_app_path); compile_succeeded = compiler->compile_exe(compiler, TRY_SOURCE_PATH, TRY_APP_BASENAME, source, source_len); clean_up_try(); return compile_succeeded; } char* chaz_ModHand_capture_output(char *source, size_t source_len, size_t *output_len) { char *captured_output = NULL; chaz_bool_t compile_succeeded; /* clear out previous versions and test to make sure removal worked */ if ( !remove_and_verify(try_app_path) ) die("Failed to delete file '%s'", try_app_path); if ( !remove_and_verify(TARGET_PATH) ) die("Failed to delete file '%s'", TARGET_PATH); /* attempt compilation; if successful, run app and slurp output */ compile_succeeded = compiler->compile_exe(compiler, TRY_SOURCE_PATH, TRY_APP_BASENAME, source, source_len); if (compile_succeeded) { system(try_app_command); captured_output = slurp_file(TARGET_PATH, output_len); } else { *output_len = 0; } /* remove all the files we just created */ clean_up_try(); return captured_output; } void chaz_ModHand_append_conf(char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(chaz_ModHand_charmony_fh, fmt, args); va_end(args); } static void clean_up_try() { remove(TRY_SOURCE_PATH); os->remove_exe(os, TRY_APP_BASENAME); remove(TARGET_PATH); } void chaz_ModHand_shorten_macro(const char *sym) { append_conf(" #define %s CHY_%s\n", sym, sym); } void chaz_ModHand_shorten_typedef(const char *sym) { append_conf(" #define %s chy_%s\n", sym, sym); } void chaz_ModHand_shorten_function(const char *sym) { append_conf(" #define %s chy_%s\n", sym, sym); } /** * Copyright 2006 The Apache Software Foundation * * Licensed 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. */