diff options
| author | Matthias Melcher <github@matthiasm.com> | 2025-07-07 23:19:35 +0200 |
|---|---|---|
| committer | Matthias Melcher <github@matthiasm.com> | 2025-07-07 23:19:41 +0200 |
| commit | 66b73c8e76a6a6d15d7061e47d79eda5c5f38f64 (patch) | |
| tree | 351222eea8613b1d2c3ad5cb20d9c558e3db7c42 /fluid/io/Code_Writer.cxx | |
| parent | 5c33d3051f06b3d0aa3514127d2cc8ee1c122874 (diff) | |
#1276: New code to generate include guard
- generating macro identifier with unicode encoding
if the filename has international character
- optional user defined include guard
Diffstat (limited to 'fluid/io/Code_Writer.cxx')
| -rw-r--r-- | fluid/io/Code_Writer.cxx | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/fluid/io/Code_Writer.cxx b/fluid/io/Code_Writer.cxx index 086244035..8bcef2f33 100644 --- a/fluid/io/Code_Writer.cxx +++ b/fluid/io/Code_Writer.cxx @@ -27,6 +27,11 @@ #include <zlib.h> +#include <string> +#include <iomanip> +#include <iostream> +#include <sstream> + using namespace fld; using namespace fld::io; using namespace fld::proj; @@ -624,15 +629,51 @@ int Code_Writer::write_code(const char *s, const char *t, bool to_codeview) { // generated by Fast Light User Interface Designer (fluid) version %.4f\n\n"; fprintf(header_file, hdr, FL_VERSION); crc_printf(hdr, FL_VERSION); - - {char define_name[102]; - const char* a = fl_filename_name(t); - char* b = define_name; - if (!isalpha(*a)) {*b++ = '_';} - while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;} - *b = 0; - fprintf(header_file, "#ifndef %s\n", define_name); - fprintf(header_file, "#define %s\n", define_name); + { + // Creating the include guard is more involved than it seems at first glance. + // The include guard is deduced from header filename. However, if the + // filename contains unicode characters, they need to be encoded using + // \Uxxxxxxxx or \\uxxxx encoding to form a valid macro identifier. + // + // But that approach is not portable. Windows does not normalize Unicode + // (ö is the letter \u00F6). macOS normalizes to NFD (ö is \u006F\u0308, + // o followed by a Combining Diaresis ¨). + // + // To make the include guard consistent across l=platforms, it can be + // explicitly set by the user in the Project Settings. + std::string macro_name_str = proj_.include_guard; + if (macro_name_str.empty()) { + std::ostringstream macro_name; + std::string header_name; + const char* a = nullptr; + if (write_codeview) { + header_name = proj_.headerfile_name(); + a = header_name.c_str(); + } else { + a = fl_filename_name(t); + } + const char* b = a + strlen(a); + int len = 0; + unsigned ucs = fl_utf8decode(a, b, &len); + if ((ucs > 127) || (!isalpha(ucs) && (ucs != '_'))) + macro_name << '_'; + while (a < b) { + ucs = fl_utf8decode(a, b, &len); + if ((ucs == '.') || (ucs == '_')) { + macro_name << '_'; + } else if (ucs > 0x0000ffff) { // large unicode character + macro_name << "\\U" << std::setw(8) << std::setfill('0') << std::hex << ucs; + } else if ((ucs > 127) || !isalnum(ucs)) { // small unicode character or not an ASCI letter or digit + macro_name << "\\u" << std::setw(4) << std::setfill('0') << std::hex << ucs; + } else { + macro_name << (char)ucs; + } + a += len; + } + macro_name_str = macro_name.str(); + } + fprintf(header_file, "#ifndef %s\n", macro_name_str.c_str()); + fprintf(header_file, "#define %s\n", macro_name_str.c_str()); } if (proj_.avoid_early_includes==0) { |
