1*3d3250a0SJeremy L Thompson // Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at 2*3d3250a0SJeremy L Thompson // the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights 3*3d3250a0SJeremy L Thompson // reserved. See files LICENSE and NOTICE for details. 4*3d3250a0SJeremy L Thompson // 5*3d3250a0SJeremy L Thompson // This file is part of CEED, a collection of benchmarks, miniapps, software 6*3d3250a0SJeremy L Thompson // libraries and APIs for efficient high-order finite element and spectral 7*3d3250a0SJeremy L Thompson // element discretizations for exascale applications. For more information and 8*3d3250a0SJeremy L Thompson // source code availability see http://github.com/ceed. 9*3d3250a0SJeremy L Thompson // 10*3d3250a0SJeremy L Thompson // The CEED research is supported by the Exascale Computing Project 17-SC-20-SC, 11*3d3250a0SJeremy L Thompson // a collaborative effort of two U.S. Department of Energy organizations (Office 12*3d3250a0SJeremy L Thompson // of Science and the National Nuclear Security Administration) responsible for 13*3d3250a0SJeremy L Thompson // the planning and preparation of a capable exascale ecosystem, including 14*3d3250a0SJeremy L Thompson // software, applications, hardware, advanced system engineering and early 15*3d3250a0SJeremy L Thompson // testbed platforms, in support of the nation's exascale computing imperative. 16*3d3250a0SJeremy L Thompson 17*3d3250a0SJeremy L Thompson #include <ceed/ceed.h> 18*3d3250a0SJeremy L Thompson #include <ceed/backend.h> 19*3d3250a0SJeremy L Thompson #include <ceed/jit-tools.h> 20*3d3250a0SJeremy L Thompson #include <stdbool.h> 21*3d3250a0SJeremy L Thompson #include <stdio.h> 22*3d3250a0SJeremy L Thompson #include <string.h> 23*3d3250a0SJeremy L Thompson 24*3d3250a0SJeremy L Thompson /** 25*3d3250a0SJeremy L Thompson @brief Load source file into initalized string buffer, including full text 26*3d3250a0SJeremy L Thompson of local files in place of `#include "local.h"` 27*3d3250a0SJeremy L Thompson 28*3d3250a0SJeremy L Thompson @param ceed A Ceed object for error handling 29*3d3250a0SJeremy L Thompson @param[in] source_file_path Absolute path to source file 30*3d3250a0SJeremy L Thompson @param[out] buffer String buffer for source file contents 31*3d3250a0SJeremy L Thompson 32*3d3250a0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 33*3d3250a0SJeremy L Thompson 34*3d3250a0SJeremy L Thompson @ref Backend 35*3d3250a0SJeremy L Thompson **/ 36*3d3250a0SJeremy L Thompson static inline int CeedLoadSourceToInitalizedBuffer(Ceed ceed, 37*3d3250a0SJeremy L Thompson const char *source_file_path, char **buffer) { 38*3d3250a0SJeremy L Thompson int ierr; 39*3d3250a0SJeremy L Thompson FILE *source_file; 40*3d3250a0SJeremy L Thompson long file_size, file_offset = 0; 41*3d3250a0SJeremy L Thompson char *temp_buffer; 42*3d3250a0SJeremy L Thompson 43*3d3250a0SJeremy L Thompson // Debug 44*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "---------- Ceed JiT ----------\n"); 45*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "Current source file: "); 46*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 255, "%s\n", source_file_path); 47*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "Current buffer:\n"); 48*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 255, "%s\n", *buffer); 49*3d3250a0SJeremy L Thompson 50*3d3250a0SJeremy L Thompson // Read file to temporary buffer 51*3d3250a0SJeremy L Thompson source_file = fopen(source_file_path, "rb"); 52*3d3250a0SJeremy L Thompson if (!source_file) 53*3d3250a0SJeremy L Thompson // LCOV_EXCL_START 54*3d3250a0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MAJOR, "Couldn't open source file: %s", 55*3d3250a0SJeremy L Thompson source_file_path); 56*3d3250a0SJeremy L Thompson // LCOV_EXCL_STOP 57*3d3250a0SJeremy L Thompson // -- Compute size of source 58*3d3250a0SJeremy L Thompson fseek(source_file, 0L, SEEK_END); 59*3d3250a0SJeremy L Thompson file_size = ftell(source_file); 60*3d3250a0SJeremy L Thompson rewind(source_file); 61*3d3250a0SJeremy L Thompson // -- Allocate memory for entire source file 62*3d3250a0SJeremy L Thompson ierr = CeedCalloc(file_size + 1, &temp_buffer); CeedChk(ierr); 63*3d3250a0SJeremy L Thompson // -- Copy the file into the buffer 64*3d3250a0SJeremy L Thompson if (1 != fread(temp_buffer, file_size, 1, source_file)) { 65*3d3250a0SJeremy L Thompson // LCOV_EXCL_START 66*3d3250a0SJeremy L Thompson fclose(source_file); 67*3d3250a0SJeremy L Thompson ierr = CeedFree(&temp_buffer); CeedChk(ierr); 68*3d3250a0SJeremy L Thompson return CeedError(ceed, CEED_ERROR_MAJOR, "Couldn't read source file: %s", 69*3d3250a0SJeremy L Thompson source_file_path); 70*3d3250a0SJeremy L Thompson // LCOV_EXCL_STOP 71*3d3250a0SJeremy L Thompson } 72*3d3250a0SJeremy L Thompson fclose(source_file); 73*3d3250a0SJeremy L Thompson 74*3d3250a0SJeremy L Thompson // Search for headers to include 75*3d3250a0SJeremy L Thompson const char *first_hash = strchr(temp_buffer, '#'); 76*3d3250a0SJeremy L Thompson while (first_hash) { 77*3d3250a0SJeremy L Thompson // -- Check for 'include' keyword 78*3d3250a0SJeremy L Thompson const char *next_e = strchr(first_hash, 'e'); 79*3d3250a0SJeremy L Thompson char keyword[8] = ""; 80*3d3250a0SJeremy L Thompson if (next_e) 81*3d3250a0SJeremy L Thompson strncpy(keyword, &next_e[-6], 7); 82*3d3250a0SJeremy L Thompson bool is_hash_include = !strcmp(keyword, "include"); 83*3d3250a0SJeremy L Thompson // ---- Spaces allowed in '# include <header.h>' 84*3d3250a0SJeremy L Thompson if (next_e) 85*3d3250a0SJeremy L Thompson for (CeedInt i = 1; first_hash - next_e + i < -6; i++) 86*3d3250a0SJeremy L Thompson is_hash_include &= first_hash[i] == ' '; 87*3d3250a0SJeremy L Thompson if (is_hash_include) { 88*3d3250a0SJeremy L Thompson // -- Copy into buffer all preceding # 89*3d3250a0SJeremy L Thompson long current_size = strlen(*buffer); 90*3d3250a0SJeremy L Thompson long copy_size = first_hash - &temp_buffer[file_offset]; 91*3d3250a0SJeremy L Thompson ierr = CeedRealloc(current_size + copy_size + 2, buffer); CeedChk(ierr); 92*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size], "\n", 2); 93*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size + 1], &temp_buffer[file_offset], copy_size); 94*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size + copy_size], "", 1); 95*3d3250a0SJeremy L Thompson // -- Load local "header.h" 96*3d3250a0SJeremy L Thompson char *next_quote = strchr(first_hash, '"'); 97*3d3250a0SJeremy L Thompson char *next_new_line = strchr(first_hash, '\n'); 98*3d3250a0SJeremy L Thompson bool is_local_header = is_hash_include && next_quote 99*3d3250a0SJeremy L Thompson && (next_new_line - next_quote > 0); 100*3d3250a0SJeremy L Thompson if (is_local_header) { 101*3d3250a0SJeremy L Thompson // ---- Build source path 102*3d3250a0SJeremy L Thompson char *include_source_path; 103*3d3250a0SJeremy L Thompson long root_length = strrchr(source_file_path, '/') - source_file_path; 104*3d3250a0SJeremy L Thompson long include_file_name_len = strchr(&next_quote[1], '"') - next_quote - 1; 105*3d3250a0SJeremy L Thompson ierr = CeedCalloc(root_length + include_file_name_len + 2, 106*3d3250a0SJeremy L Thompson &include_source_path); CeedChk(ierr); 107*3d3250a0SJeremy L Thompson strncpy(include_source_path, source_file_path, root_length + 1); 108*3d3250a0SJeremy L Thompson strncpy(&include_source_path[root_length + 1], &next_quote[1], 109*3d3250a0SJeremy L Thompson include_file_name_len); 110*3d3250a0SJeremy L Thompson strncpy(&include_source_path[root_length + include_file_name_len + 1], "", 1); 111*3d3250a0SJeremy L Thompson // ---- Recursive call to load source to buffer 112*3d3250a0SJeremy L Thompson ierr = CeedLoadSourceToInitalizedBuffer(ceed, include_source_path, buffer); 113*3d3250a0SJeremy L Thompson CeedChk(ierr); 114*3d3250a0SJeremy L Thompson ierr = CeedFree(&include_source_path); CeedChk(ierr); 115*3d3250a0SJeremy L Thompson } 116*3d3250a0SJeremy L Thompson file_offset = strchr(first_hash, '\n') - temp_buffer + 1; 117*3d3250a0SJeremy L Thompson } 118*3d3250a0SJeremy L Thompson // -- Next hash 119*3d3250a0SJeremy L Thompson first_hash = strchr(&first_hash[1], '#'); 120*3d3250a0SJeremy L Thompson } 121*3d3250a0SJeremy L Thompson // Copy rest of source file into buffer 122*3d3250a0SJeremy L Thompson long current_size = strlen(*buffer); 123*3d3250a0SJeremy L Thompson long copy_size = strlen(&temp_buffer[file_offset]); 124*3d3250a0SJeremy L Thompson ierr = CeedRealloc(current_size + copy_size + 2, buffer); CeedChk(ierr); 125*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size], "\n", 2); 126*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size + 1], &temp_buffer[file_offset], copy_size); 127*3d3250a0SJeremy L Thompson strncpy(&(*buffer)[current_size + copy_size + 1], "", 1); 128*3d3250a0SJeremy L Thompson 129*3d3250a0SJeremy L Thompson // Cleanup 130*3d3250a0SJeremy L Thompson ierr = CeedFree(&temp_buffer); CeedChk(ierr); 131*3d3250a0SJeremy L Thompson 132*3d3250a0SJeremy L Thompson // Debug 133*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "---------- Ceed JiT ----------\n"); 134*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "Current source file: "); 135*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 255, "%s\n", source_file_path); 136*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 1, "Final buffer:\n"); 137*3d3250a0SJeremy L Thompson CeedDebug256(ceed, 255, "%s\n", *buffer); 138*3d3250a0SJeremy L Thompson 139*3d3250a0SJeremy L Thompson return CEED_ERROR_SUCCESS; 140*3d3250a0SJeremy L Thompson } 141*3d3250a0SJeremy L Thompson 142*3d3250a0SJeremy L Thompson /** 143*3d3250a0SJeremy L Thompson @brief Initalize and load source file into string buffer, including full text 144*3d3250a0SJeremy L Thompson of local files in place of `#include "local.h"`. 145*3d3250a0SJeremy L Thompson Note: Caller is responsible for freeing the string buffer with `CeedFree()`. 146*3d3250a0SJeremy L Thompson 147*3d3250a0SJeremy L Thompson @param ceed A Ceed object for error handling 148*3d3250a0SJeremy L Thompson @param[in] source_file_path Absolute path to source file 149*3d3250a0SJeremy L Thompson @param[out] buffer String buffer for source file contents 150*3d3250a0SJeremy L Thompson 151*3d3250a0SJeremy L Thompson @return An error code: 0 - success, otherwise - failure 152*3d3250a0SJeremy L Thompson 153*3d3250a0SJeremy L Thompson @ref Backend 154*3d3250a0SJeremy L Thompson **/ 155*3d3250a0SJeremy L Thompson int CeedLoadSourceToBuffer(Ceed ceed, const char *source_file_path, 156*3d3250a0SJeremy L Thompson char **buffer) { 157*3d3250a0SJeremy L Thompson int ierr; 158*3d3250a0SJeremy L Thompson 159*3d3250a0SJeremy L Thompson // Initalize buffer 160*3d3250a0SJeremy L Thompson ierr = CeedCalloc(1, buffer); CeedChk(ierr); 161*3d3250a0SJeremy L Thompson 162*3d3250a0SJeremy L Thompson // Load to initalized buffer 163*3d3250a0SJeremy L Thompson ierr = CeedLoadSourceToInitalizedBuffer(ceed, source_file_path, buffer); 164*3d3250a0SJeremy L Thompson CeedChk(ierr); 165*3d3250a0SJeremy L Thompson 166*3d3250a0SJeremy L Thompson return CEED_ERROR_SUCCESS; 167*3d3250a0SJeremy L Thompson } 168