From: Fletcher T. Penney Date: Thu, 25 May 2017 00:55:22 +0000 (-0400) Subject: CHANGED: Add mmd_convert_to_data functions; Refactor main.c so that EPUB and other... X-Git-Tag: 6.0.7^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=059fd645a04c006ed449628983141995c42002d5;p=multimarkdown CHANGED: Add mmd_convert_to_data functions; Refactor main.c so that EPUB and other formats use same workflow -- batch mode no longer required for EPUB format --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 012d324..84b578f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ set(src_files Sources/libMultiMarkdown/transclude.c Sources/libMultiMarkdown/uuid.c Sources/libMultiMarkdown/writer.c + Sources/libMultiMarkdown/zip.c ) # Primary header files, also for doxygen documentation @@ -227,6 +228,7 @@ set(header_files Sources/libMultiMarkdown/uthash.h Sources/libMultiMarkdown/uuid.h Sources/libMultiMarkdown/writer.h + Sources/libMultiMarkdown/zip.h ) set (scripts diff --git a/Sources/libMultiMarkdown/epub.c b/Sources/libMultiMarkdown/epub.c index 6a0a3a8..1dc79a1 100644 --- a/Sources/libMultiMarkdown/epub.c +++ b/Sources/libMultiMarkdown/epub.c @@ -61,16 +61,14 @@ #include #endif -#include "d_string.h" #include "epub.h" #include "html.h" #include "i18n.h" #include "miniz.h" -#include "mmd.h" #include "transclude.h" #include "uuid.h" #include "writer.h" - +#include "zip.h" #define print(x) d_string_append(out, x) #define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1) @@ -295,7 +293,10 @@ char * epub_nav(mmd_engine * e, scratch_pad * scratch) { } -bool add_asset_from_file(const char * filepath, asset * a, const char * destination, const char * directory) { +bool add_asset_from_file(mz_zip_archive * pZip, asset * a, const char * destination, const char * directory) { + if (!directory) + return false; + char * path = path_from_dir_base(directory, a->url); mz_bool status; bool result = false; @@ -303,7 +304,7 @@ bool add_asset_from_file(const char * filepath, asset * a, const char * destinat DString * buffer = scan_file(path); if (buffer && buffer->currentStringLength > 0) { - status = mz_zip_add_mem_to_archive_file_in_place(filepath, destination, buffer->str, buffer->currentStringLength, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(pZip, destination, buffer->str, buffer->currentStringLength, MZ_BEST_COMPRESSION); d_string_free(buffer, true); result = true; @@ -344,7 +345,7 @@ static size_t write_memory(void * contents, size_t size, size_t nmemb, void * us } // Add assets to zipfile using libcurl -void add_assets(const char * filepath, mmd_engine * e, const char * directory) { +void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * directory) { asset * a, * a_tmp; if (e->asset_hash){ @@ -375,12 +376,12 @@ void add_assets(const char * filepath, mmd_engine * e, const char * directory) { if (res != CURLE_OK) { // Attempt to add asset from local file - if (!add_asset_from_file(filepath, a, destination, directory)) { + if (!add_asset_from_file(pZip, a, destination, directory)) { fprintf(stderr, "Unable to store '%s' in EPUB\n", a->url); } } else { // Store downloaded file in zip - status = mz_zip_add_mem_to_archive_file_in_place(filepath, destination, chunk.memory, chunk.size, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(pZip, destination, chunk.memory, chunk.size, MZ_BEST_COMPRESSION); } } } @@ -388,7 +389,7 @@ void add_assets(const char * filepath, mmd_engine * e, const char * directory) { #else // Add local assets only (libcurl not available) -void add_assets(const char * filepath, mmd_engine * e, const char * directory) { +void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * directory) { asset * a, * a_tmp; if (e->asset_hash){ @@ -403,7 +404,7 @@ void add_assets(const char * filepath, mmd_engine * e, const char * directory) { memcpy(&destination[13], a->asset_path, 36); // Attempt to add asset from local file - if (!add_asset_from_file(filepath, a, destination, directory)) { + if (!add_asset_from_file(pZip, a, destination, directory)) { fprintf(stderr, "Unable to store '%s' in EPUB\n", a->url); } } @@ -414,53 +415,76 @@ void add_assets(const char * filepath, mmd_engine * e, const char * directory) { // Use the miniz library to create a zip archive for the EPUB document void epub_write_wrapper(const char * filepath, const char * body, mmd_engine * e, const char * directory) { + FILE * output_stream; + + DString * result = epub_create(body, e, directory); + + if (!(output_stream = fopen(filepath, "w"))) { + // Failed to open file + perror(filepath); + } else { + fwrite(&(result->str), result->currentStringLength, 1, output_stream); + fclose(output_stream); + } + + d_string_free(result, true); +} + + +DString * epub_create(const char * body, mmd_engine * e, const char * directory) { + DString * result = d_string_new(""); scratch_pad * scratch = scratch_pad_new(e, FORMAT_EPUB); + mz_bool status; char * data; size_t len; - // Delete existing file, if present - remove(filepath); + mz_zip_archive zip; + zip_new_archive(&zip); // Add mimetype data = epub_mimetype(); len = strlen(data); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "mimetype", data, len, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "mimetype", data, len, MZ_BEST_COMPRESSION); free(data); // Create directories - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "OEBPS/", NULL, 0, NULL, 0, MZ_BEST_COMPRESSION); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "META-INF/", NULL, 0, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "OEBPS/", NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "META-INF/", NULL, 0, MZ_BEST_COMPRESSION); // Add container data = epub_container_xml(); len = strlen(data); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "META-INF/container.xml", data, len, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "META-INF/container.xml", data, len, MZ_BEST_COMPRESSION); free(data); // Add package data = epub_package_document(scratch); len = strlen(data); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "OEBPS/main.opf", data, len, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "OEBPS/main.opf", data, len, MZ_BEST_COMPRESSION); free(data); // Add nav data = epub_nav(e, scratch); len = strlen(data); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "OEBPS/nav.xhtml", data, len, NULL, 0, MZ_BEST_COMPRESSION); + status = mz_zip_writer_add_mem(&zip, "OEBPS/nav.xhtml", data, len, MZ_BEST_COMPRESSION); free(data); // Add main document len = strlen(body); - status = mz_zip_add_mem_to_archive_file_in_place(filepath, "OEBPS/main.xhtml", body, len, NULL, 0, MZ_BEST_COMPRESSION); - + status = mz_zip_writer_add_mem(&zip, "OEBPS/main.xhtml", body, len, MZ_BEST_COMPRESSION); // Add assets - add_assets(filepath, e, directory); + add_assets(&zip, e, directory); scratch_pad_free(scratch); -} + // Finalize zip archive and extract data + free(result->str); + + status = mz_zip_writer_finalize_heap_archive(&zip, (void **) &(result->str), &(result->currentStringLength)); + return result; +} diff --git a/Sources/libMultiMarkdown/epub.h b/Sources/libMultiMarkdown/epub.h index e778297..2f9e2e9 100644 --- a/Sources/libMultiMarkdown/epub.h +++ b/Sources/libMultiMarkdown/epub.h @@ -58,9 +58,12 @@ #ifndef EPUB_MULTIMARKDOWN_H #define EPUB_MULTIMARKDOWN_H +#include "d_string.h" #include "mmd.h" void epub_write_wrapper(const char * root_path, const char * body, mmd_engine * e, const char * directory); +DString * epub_create(const char * body, mmd_engine * e, const char * directory); + #endif diff --git a/Sources/libMultiMarkdown/include/libMultiMarkdown.h b/Sources/libMultiMarkdown/include/libMultiMarkdown.h index 236760c..d74282c 100644 --- a/Sources/libMultiMarkdown/include/libMultiMarkdown.h +++ b/Sources/libMultiMarkdown/include/libMultiMarkdown.h @@ -94,6 +94,12 @@ char * mmd_string_convert(const char * source, unsigned long extensions, short format, short language); +/// Convert MMD text to specified format using DString as a container for block of data +/// and length of that block. Must be used for "complex" output formats such as EPUB. +/// Returned DString * must be freed +DString * mmd_string_convert_to_data(const char * source, unsigned long extensions, short format, short language, const char * directory); + + /// Convert MMD text and write results to specified file -- used for "complex" output formats requiring /// multiple documents (e.g. EPUB) void mmd_string_convert_to_file(const char * source, unsigned long extensions, short format, short language, const char * directory, const char * filepath); @@ -124,6 +130,12 @@ char * mmd_string_metavalue_for_key(char * source, const char * key); char * mmd_d_string_convert(DString * source, unsigned long extensions, short format, short language); +/// Convert MMD text to specified format using DString as a container for block of data +/// and length of that block. Must be used for "complex" output formats such as EPUB. +/// Returned DString * must be freed +DString * mmd_d_string_convert_to_data(DString * source, unsigned long extensions, short format, short language, const char * directory); + + /// Convert MMD text and write results to specified file -- used for "complex" output formats requiring /// multiple documents (e.g. EPUB) void mmd_d_string_convert_to_file(DString * source, unsigned long extensions, short format, short language, const char * directory, const char * filepath); @@ -205,6 +217,12 @@ char * mmd_engine_convert(mmd_engine * e, short format); void mmd_engine_convert_to_file(mmd_engine * e, short format, const char * directory, const char * filepath); +/// Convert MMD text to specified format using DString as a container for block of data +/// and length of that block. Must be used for "complex" output formats such as EPUB. +/// Returned DString * must be freed +DString * mmd_engine_convert_to_data(mmd_engine * e, short format, const char * directory); + + /// Does the text have metadata? bool mmd_engine_has_metadata(mmd_engine * e, size_t * end); diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 902e64d..6eab95c 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -2203,6 +2203,55 @@ void mmd_engine_convert_to_file(mmd_engine * e, short format, const char * direc } +DString * mmd_string_convert_to_data(const char * source, unsigned long extensions, short format, short language, const char * directory) { + mmd_engine * e = mmd_engine_create_with_string(source, extensions); + + mmd_engine_set_language(e, language); + + DString * result = mmd_engine_convert_to_data(e, format, directory); + + mmd_engine_free(e, true); + + return result; +} + + +DString * mmd_d_string_convert_to_data(DString * source, unsigned long extensions, short format, short language, const char * directory) { + mmd_engine * e = mmd_engine_create_with_dstring(source, extensions); + + mmd_engine_set_language(e, language); + + DString * result = mmd_engine_convert_to_data(e, format, directory); + + mmd_engine_free(e, false); // The engine doesn't own the DString, so don't free it. + + return result; +} + + +DString * mmd_engine_convert_to_data(mmd_engine * e, short format, const char * directory) { + DString * output = d_string_new(""); + DString * result = NULL; + + mmd_engine_parse_string(e); + + mmd_engine_export_token_tree(output, e, format); + + switch (format) { + case FORMAT_EPUB: + result = epub_create(output->str, e, directory); + + d_string_free(output, true); + break; + default: + result = output; + break; + } + + return result; +} + + /// Return string containing engine version. char * mmd_version(void) { char * result; diff --git a/Sources/libMultiMarkdown/zip.c b/Sources/libMultiMarkdown/zip.c new file mode 100644 index 0000000..88cba3e --- /dev/null +++ b/Sources/libMultiMarkdown/zip.c @@ -0,0 +1,120 @@ +/** + + MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more. + + @file zip.c + + @brief Common routines for zip-based file formats + + + @author Fletcher T. Penney + @bug + +**/ + +/* + + Copyright © 2016 - 2017 Fletcher T. Penney. + + + The `MultiMarkdown 6` project is released under the MIT License.. + + GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project: + + https://github.com/fletcher/MultiMarkdown-4/ + + MMD 4 is released under both the MIT License and GPL. + + + CuTest is released under the zlib/libpng license. See CuTest.c for the + text of the license. + + uthash library: + Copyright (c) 2005-2016, Troy D. Hanson + + Licensed under Revised BSD license + + miniz library: + Copyright 2013-2014 RAD Game Tools and Valve Software + Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + + Licensed under the MIT license + + argtable3 library: + Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + + All rights reserved. + + Licensed under the Revised BSD License + + + ## The MIT License ## + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + ## Revised BSD License ## + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR + PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +*/ + + +#include "miniz.h" +#include "zip.h" + + +void zip_new_archive(mz_zip_archive * pZip) { + memset(pZip, 0, sizeof(mz_zip_archive)); + + mz_bool status; + + status = mz_zip_writer_init_heap(pZip, 0, 0); + + if (!status) { + fprintf(stderr, "mz_zip_writer_init_heap() failed.\n"); + } +} + diff --git a/Sources/libMultiMarkdown/zip.h b/Sources/libMultiMarkdown/zip.h new file mode 100644 index 0000000..64c3549 --- /dev/null +++ b/Sources/libMultiMarkdown/zip.h @@ -0,0 +1,111 @@ +/** + + MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more. + + @file zip.h + + @brief + + + @author Fletcher T. Penney + @bug + +**/ + +/* + + Copyright © 2016 - 2017 Fletcher T. Penney. + + + The `MultiMarkdown 6` project is released under the MIT License.. + + GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project: + + https://github.com/fletcher/MultiMarkdown-4/ + + MMD 4 is released under both the MIT License and GPL. + + + CuTest is released under the zlib/libpng license. See CuTest.c for the + text of the license. + + uthash library: + Copyright (c) 2005-2016, Troy D. Hanson + + Licensed under Revised BSD license + + miniz library: + Copyright 2013-2014 RAD Game Tools and Valve Software + Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC + + Licensed under the MIT license + + argtable3 library: + Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + + All rights reserved. + + Licensed under the Revised BSD License + + + ## The MIT License ## + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + ## Revised BSD License ## + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR + PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +*/ + + +#ifndef ZIP_MULTIMARKDOWN_H +#define ZIP_MULTIMARKDOWN_H + +void zip_new_archive(mz_zip_archive * pZip); + + +#endif diff --git a/Sources/multimarkdown/main.c b/Sources/multimarkdown/main.c index b279c5c..0366efb 100644 --- a/Sources/multimarkdown/main.c +++ b/Sources/multimarkdown/main.c @@ -287,7 +287,8 @@ int main(int argc, char** argv) { } DString * buffer = NULL; - char * result = NULL; + DString * result = NULL; + char * char_result = NULL; FILE * output_stream; char * output_filename; @@ -360,46 +361,40 @@ int main(int argc, char** argv) { #endif if (a_meta->count > 0) { // List metadata keys - result = mmd_string_metadata_keys(buffer->str); + char_result = mmd_string_metadata_keys(buffer->str); - fputs(result, stdout); + fputs(char_result, stdout); - free(result); + free(char_result); } else if (a_extract->count > 0) { // Extract metadata key const char * query = a_extract->sval[0]; - result = mmd_string_metavalue_for_key(buffer->str, query); + char_result = mmd_string_metavalue_for_key(buffer->str, query); - fputs(result, stdout); + fputs(char_result, stdout); fputc('\n', stdout); - free(result); + free(char_result); } else { // Regular processing - if (FORMAT_EPUB == format) { - mmd_d_string_convert_to_file(buffer, extensions, format, language, folder, output_filename); - result = NULL; - } else if (FORMAT_MMD == format) { - result = buffer->str; + if (FORMAT_MMD == format) { + result = buffer; } else { - result = mmd_d_string_convert(buffer, extensions, format, language); + result = mmd_d_string_convert_to_data(buffer, extensions, format, language, folder); } - if (result) { - if (!(output_stream = fopen(output_filename, "w"))) { - // Failed to open file - perror(output_filename); - } else { - fputs(result, output_stream); - fputc('\n', output_stream); - fclose(output_stream); - } + if (!(output_stream = fopen(output_filename, "w"))) { + // Failed to open file + perror(output_filename); + } else { + fwrite(result->str, result->currentStringLength, 1, output_stream); + fclose(output_stream); } if (FORMAT_MMD != format) { - free(result); + d_string_free(result, true); } } @@ -434,9 +429,14 @@ int main(int argc, char** argv) { buffer = stdin_buffer(); } + char * folder = NULL; + + if (a_file->count == 1) { + folder = dirname((char *) a_file->filename[0]); + } + if ((extensions & EXT_TRANSCLUDE) && (a_file->count == 1)) { // Perform transclusion(s) - char * folder = dirname((char *) a_file->filename[0]); mmd_transclude_source(buffer, folder, "", format, NULL, NULL); @@ -454,28 +454,28 @@ int main(int argc, char** argv) { if (a_meta->count > 0) { // List metadata keys - result = mmd_string_metadata_keys(buffer->str); + char_result = mmd_string_metadata_keys(buffer->str); - fputs(result, stdout); + fputs(char_result, stdout); - free(result); + free(char_result); } else if (a_extract->count > 0) { // Extract metadata key const char * query = a_extract->sval[0]; - result = mmd_string_metavalue_for_key(buffer->str, query); + char_result = mmd_string_metavalue_for_key(buffer->str, query); - fputs(result, stdout); + fputs(char_result, stdout); fputc('\n', stdout); - free(result); + free(char_result); } else { // Regular processing if (FORMAT_MMD == format) { - result = buffer->str; + result = buffer; } else { - result = mmd_d_string_convert(buffer, extensions, format, language); + result = mmd_d_string_convert_to_data(buffer, extensions, format, language, folder); } // Where does output go? @@ -491,14 +491,13 @@ int main(int argc, char** argv) { goto exit; } - fputs(result, output_stream); - fputc('\n', output_stream); - + fwrite(result->str, result->currentStringLength, 1, output_stream); + if (output_stream != stdout) fclose(output_stream); if (FORMAT_MMD != format) { - free(result); + d_string_free(result, true); } }