Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: ncurses module does not have wide character support #3530

Closed
davidzchen opened this issue Jan 5, 2025 · 5 comments · Fixed by #3545
Closed

[Bug]: ncurses module does not have wide character support #3530

davidzchen opened this issue Jan 5, 2025 · 5 comments · Fixed by #3545
Labels
bug Something isn't working

Comments

@davidzchen
Copy link
Member

davidzchen commented Jan 5, 2025

I'm not sure if "bug" is the best category for this, but at this moment, I am not requesting a new module, and this is also not a security vulnerability.

What happened?

The ncurses module has no wide character support. I attempted to add wide character support, but ran into problems. See details below.

Version

Development (host) and target OS/architectures:

  • macOS Sequoia 15.2
  • Ubuntu 24.04.1

Output of bazel --version:

bazel 8.0.0

Version of relevant rules from the WORKSPACE or MODULE.bazel file:

bazel_dep(name = "ncurses", version = "6.4.20221231.bcr.3")

Language(s) and/or frameworks involved:

C, C++

How to reproduce

To reproduce the lack of wide character support:

git clone https://github.com/davidzchen/bazel-ncurses-example
cd bazel-ncurses-example
bazel run //foo:main

Note that the character is being rendered as ~V~H.

Any other information?

I understand that this is because the ncurses module is currently not being built with wide character support. I am unsure whether we should create a new ncursesw module or enable wide character support in the ncurses module itself.

Either way, I attempted to enable wide character support but ran into some problems.

I copied the files from the ncurses module in the BCR, including the BUILD file for the ncurses repository and other needed files, such as the rule implementations for pseudo_configure and automake_substitution, into my repository using the module extension setup. See: https://github.com/davidzchen/bazel-ncurses-example/tree/module-extension

Then, I added NCURSES_WIDECHAR and USE_WIDEC_SUPPORT to the defs for the pseudo_configure rule that generates ncurses_cfg.h:

pseudo_configure(
    name = "ncurses_cfg_h",
    src = "include/ncurses_cfg.hin",
    out = "include/ncurses_cfg.h",
    defs = [
        ...
        "NCURSES_WIDECHAR",
        "USE_WIDEC_SUPPORT",
    ],
    mappings = {
        ...
    },
)

However, when I tried to bazel build @ncurses, I get the following errors:

macOS 15.2:

$ bazel build @ncurses
INFO: Analyzed target @@+ncurses_repository+ncurses//:ncurses (0 packages loaded, 0 targets configured).
ERROR: /private/var/tmp/_bazel_dzc/87450ce08cbc0c792b19d6253d30d152/external/+ncurses_repository+ncurses/BUILD.bazel:279:10: Compiling ncurses/tinfo/make_keys.c [for tool] failed: (Exit 1): cc_wrapper.sh failed: error executing CppCompile command (from target @@+ncurses_repository+ncurses//:make_keys) external/rules_cc++cc_configure_extension+local_config_cc/cc_wrapper.sh -U_FORTIFY_SOURCE -fstack-protector -Wall -Wthread-safety -Wself-assign -Wunused-but-set-parameter -Wno-free-nonheap-object ... (remaining 44 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/+ncurses_repository+ncurses/ncurses/tinfo/make_keys.c:41:
In file included from external/+ncurses_repository+ncurses/ncurses/build.priv.h:70:
In file included from bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/+ncurses_repository+ncurses/include/curses.h:456:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h:67:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wchar.h:76:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h:32:28: error: cannot combine with previous 'type-name' declaration specifier
   32 | typedef __darwin_mbstate_t mbstate_t;
      |                            ^
bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/+ncurses_repository+ncurses/include/ncurses_cfg.h:201:19: note: expanded from macro 'mbstate_t'
  201 | #define mbstate_t int
      |                   ^
1 error generated.
ERROR: /private/var/tmp/_bazel_dzc/87450ce08cbc0c792b19d6253d30d152/external/+ncurses_repository+ncurses/BUILD.bazel:214:10: Compiling ncurses/tinfo/make_hash.c [for tool] failed: (Exit 1): cc_wrapper.sh failed: error executing CppCompile command (from target @@+ncurses_repository+ncurses//:make_hash) external/rules_cc++cc_configure_extension+local_config_cc/cc_wrapper.sh -U_FORTIFY_SOURCE -fstack-protector -Wall -Wthread-safety -Wself-assign -Wunused-but-set-parameter -Wno-free-nonheap-object ... (remaining 44 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/+ncurses_repository+ncurses/ncurses/tinfo/make_hash.c:40:
In file included from external/+ncurses_repository+ncurses/ncurses/build.priv.h:70:
In file included from bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/+ncurses_repository+ncurses/include/curses.h:456:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/wchar.h:67:
In file included from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/_wchar.h:76:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h:32:28: error: cannot combine with previous 'type-name' declaration specifier
   32 | typedef __darwin_mbstate_t mbstate_t;
      |                            ^
bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/+ncurses_repository+ncurses/include/ncurses_cfg.h:201:19: note: expanded from macro 'mbstate_t'
  201 | #define mbstate_t int
      |                   ^
1 error generated.
Target @@+ncurses_repository+ncurses//:ncurses failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.627s, Critical Path: 0.11s
INFO: 4 processes: 4 internal.
ERROR: Build did NOT complete successfully

Ubuntu 24.04:

$ bazel build @ncurses
INFO: Analyzed target @@+ncurses_repository+ncurses//:ncurses (0 packages loaded, 0 targets configured).
ERROR: /home/dzc/.cache/bazel/_bazel_dzc/0eea61d75b5304f994b8af9040b68be8/external/+ncurses_repository+ncurses/BUILD.bazel:279:10: Compiling ncurses/tinfo/make_keys.c [for tool] failed: (Exit 1): gcc failed: error executing CppCompile command (from target @@+ncurses_repository+ncurses//:make_keys) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 36 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/+ncurses_repository+ncurses/ncurses/build.priv.h:53,
                 from external/+ncurses_repository+ncurses/ncurses/tinfo/make_keys.c:41:
/usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h:6:21: error: two or more data types in declaration specifiers
    6 | typedef __mbstate_t mbstate_t;
      |                     ^~~~~~~~~
ERROR: /home/dzc/.cache/bazel/_bazel_dzc/0eea61d75b5304f994b8af9040b68be8/external/+ncurses_repository+ncurses/BUILD.bazel:214:10: Compiling ncurses/tinfo/make_hash.c [for tool] failed: (Exit 1): gcc failed: error executing CppCompile command (from target @@+ncurses_repository+ncurses//:make_hash) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -g0 -O2 '-D_FORTIFY_SOURCE=1' -DNDEBUG -ffunction-sections ... (remaining 36 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/+ncurses_repository+ncurses/ncurses/build.priv.h:53,
                 from external/+ncurses_repository+ncurses/ncurses/tinfo/make_hash.c:40:
/usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h:6:21: error: two or more data types in declaration specifiers
    6 | typedef __mbstate_t mbstate_t;
      |                     ^~~~~~~~~
Target @@+ncurses_repository+ncurses//:ncurses failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.364s, Critical Path: 0.11s
INFO: 3 processes: 3 internal.
ERROR: Build did NOT complete successfully

Another data point is that cloning the ncurses repository from https://github.com/mirror/ncurses, then running ./configure --enable-widec, then make succeeds, so there must be something else we are missing in the BUILD file.

I am at a loss as to why both clang/llvm and gcc are reporting this compilation error in a system header. I tried to search for this error message on Google, and all the results seem to point to this error message indicating a syntax error, which does not seem to make sense here.

@davidzchen davidzchen added the bug Something isn't working label Jan 5, 2025
@davidzchen
Copy link
Member Author

+cc maintainer of this module: @wep21

@davidzchen
Copy link
Member Author

Digging into this more, I compared the ncurses_cfg.h from ./configure (which I have published in this Gist) and the one generated by Bazel, and I noticed this:

Screenshot 2025-01-05 at 04 08 00

In the one generated by Bazel, there is an extra #define mbstate_t int as shown above. It looks like this is due to the entry "mbstate_t": "int" in the pseudo_configure mappings.

This seems to explain the above error:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/_types/_mbstate_t.h:32:28: error: cannot combine with previous 'type-name' declaration specifier
   32 | typedef __darwin_mbstate_t mbstate_t;
      |                            ^
bazel-out/darwin_arm64-opt-exec-ST-d57f47055a04/bin/external/+ncurses_repository+ncurses/include/ncurses_cfg.h:201:19: note: expanded from macro 'mbstate_t'
  201 | #define mbstate_t int
      |       

Removing the "mbstate_t": "int" entry results in the following error:

In file included from external/+ncurses_repository+ncurses/ncurses/base/define_key.c:35:
external/+ncurses_repository+ncurses/ncurses/curses.priv.h:2192:1: error: unknown type name 'make'
 2192 | make an error
      | ^
external/+ncurses_repository+ncurses/ncurses/curses.priv.h:2192:8: error: expected ';' after top level declarator
 2192 | make an error
      |        ^
2 errors generated.

Looking at external/+ncurses_repository+ncurses/ncurses/curses.priv.h at that location, there is this code:

  /*
   * Wide-character macros to hide some platform-differences.
   */
  #if USE_WIDEC_SUPPORT

  #if defined(_NC_WINDOWS) && !defined(_NC_MSC) && !defined(EXP_WIN32_DRIVER)
  /*
   * MinGW has wide-character functions, but they do not work correctly.
   */
  extern int __MINGW_NOTHROW _nc_wctomb(char *, wchar_t);
  #define wctomb(s,wc) _nc_wctomb(s,wc)
  #define wcrtomb(s,wc,n) _nc_wctomb(s,wc)

  extern int __MINGW_NOTHROW _nc_mbtowc(wchar_t *, const char *, size_t);
  #define mbtowc(pwc,s,n) _nc_mbtowc(pwc,s,n)

  extern int __MINGW_NOTHROW _nc_mblen(const char *, size_t);
  #define mblen(s,n) _nc_mblen(s, n)

  #endif /* _NC_WINDOWS && !_NC_MSC */

  #if HAVE_MBTOWC && HAVE_MBLEN
  #define reset_mbytes(state) IGNORE_RC(mblen(NULL, (size_t) 0)), IGNORE_RC(mbtowc(NULL, NULL, (size_t) 0))
  #define count_mbytes(buffer,length,state) mblen(buffer,length)
  #define check_mbytes(wch,buffer,length,state) \
    (int) mbtowc(&(wch), buffer, length)
  #define state_unused
  #elif HAVE_MBRTOWC && HAVE_MBRLEN
  #define reset_mbytes(state) init_mb(state)
  #define count_mbytes(buffer,length,state) mbrlen(buffer,length,&(state))
  #define check_mbytes(wch,buffer,length,state) \
    (int) mbrtowc(&(wch), buffer, length, &(state))
  #else
  make an error
  #endif

  #endif /* USE_WIDEC_SUPPORT */

The ncurses_cfg.h generated by ./configure does have HAVE_MBTOWC, HAVE_MBLEN, and HAVE_MBRTOWC defined as 1, which I added to defs as well. Here is my diff at this point:

Screenshot 2025-01-05 at 04 29 23

Running bazel build @ncurses now seems to make it past the mbstate_t-related error. However, there are now a lot of errors reporting that chtype is not defined, for example:

external/+ncurses_repository+ncurses/ncurses/base/lib_box.c:53:5: error: member reference base type 'chtype' (aka 'unsigned int') is not a structure or union
   53 |     SetChar2(wch, ch);
      |     ^~~~~~~~~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/curses.priv.h:1461:29: note: expanded from macro 'SetChar2'
 1461 | #define SetChar2(wch,ch)    SetChar(wch,ChCharOf(ch),ChAttrOf(ch))
      |                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/curses.priv.h:1362:11: note: expanded from macro 'SetChar'
 1362 |                             _cp->chars[0] = (wchar_t) (c);                          \
      |                             ~~~^ ~~~~~

@davidzchen
Copy link
Member Author

davidzchen commented Jan 5, 2025

I have pasted my curses.priv.h here in case it helps: https://gist.github.com/davidzchen/cb8f3347800b7ed9796b4f46d397b365

I have not yet found where chtype is supposed to be defined.

Interestingly, on Linux, there are instead errors like these, reporting that members attr and chars are being requested on a a type that is not a struct or a union, which also puzzles me:

$ bazel build @ncurses
INFO: Analyzed target @@+ncurses_repository+ncurses//:ncurses (1 packages loaded, 279 targets configured).
INFO: From Executing genrule @@+ncurses_repository+ncurses//:lib_gen_c:
.. adding -P option to work around /bin/cpp 13
ERROR: /home/dzc/.cache/bazel/_bazel_dzc/0eea61d75b5304f994b8af9040b68be8/external/+ncurses_repository+ncurses/BUILD.bazel:119:11: Compiling ncurses/base/lib_addstr.c failed: (Exit 1): gcc failed: error executing CppCompile command (from target @@+ncurses_repository+ncurses//:ncurses) /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer -MD -MF ... (remaining 29 arguments skipped)

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
In file included from external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:46:
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c: In function 'waddnstr':
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:70:13: error: request for member 'chars' in something not a structure or union
   70 |             SetChar(ch, UChar(*str++), A_NORMAL);
      |             ^~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:70:13: error: request for member 'attr' in something not a structure or union
   70 |             SetChar(ch, UChar(*str++), A_NORMAL);
      |             ^~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c: In function 'waddchnstr':
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:110:9: error: request for member 'chars' in something not a structure or union
  110 |         SetChar2(line->text[i + x], astr[i]);
      |         ^~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:110:9: error: request for member 'attr' in something not a structure or union
  110 |         SetChar2(line->text[i + x], astr[i]);
      |         ^~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c: In function 'wadd_wchnstr':
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:168:18: error: request for member 'attr' in something not a structure or union
  168 |     if (x > 0 && isWidecExt(line->text[x])) {
      |                  ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:168:18: error: request for member 'attr' in something not a structure or union
  168 |     if (x > 0 && isWidecExt(line->text[x])) {
      |                  ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:170:18: error: request for member 'attr' in something not a structure or union
  170 |             if (!isWidecExt(line->text[x - i])) {
      |                  ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:170:18: error: request for member 'attr' in something not a structure or union
  170 |             if (!isWidecExt(line->text[x - i])) {
      |                  ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:191:49: error: incompatible type for argument 2 of '_nc_render'
  191 |             line->text[x] = _nc_render(win, astr[i]);
      |                                             ~~~~^~~
      |                                                 |
      |                                                 cchar_t
In file included from external/+ncurses_repository+ncurses/ncurses/curses.priv.h:354:
external/+ncurses_repository+ncurses/ncurses/curses.priv.h:2129:59: note: expected 'chtype' {aka 'unsigned int'} but argument is of type 'cchar_t'
 2129 | extern NCURSES_EXPORT(NCURSES_CH_T) _nc_render (WINDOW *, NCURSES_CH_T);
      |                                                           ^~~~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:197:21: error: request for member 'attr' in something not a structure or union
  197 |                     SetWidecExt(line->text[x + j], j);
      |                     ^~~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:197:21: error: request for member 'attr' in something not a structure or union
  197 |                     SetWidecExt(line->text[x + j], j);
      |                     ^~~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:213:31: error: request for member 'attr' in something not a structure or union
  213 |     while (x <= win->_maxx && isWidecExt(line->text[x])) {
      |                               ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:213:31: error: request for member 'attr' in something not a structure or union
  213 |     while (x <= win->_maxx && isWidecExt(line->text[x])) {
      |                               ^~~~~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c: In function 'waddnwstr':
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:243:13: error: request for member 'chars' in something not a structure or union
  243 |             SetChar(ch, *str++, A_NORMAL);
      |             ^~~~~~~
external/+ncurses_repository+ncurses/ncurses/base/lib_addstr.c:243:13: error: request for member 'attr' in something not a structure or union
  243 |             SetChar(ch, *str++, A_NORMAL);
      |             ^~~~~~~
Target @@+ncurses_repository+ncurses//:ncurses failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 1.047s, Critical Path: 0.36s
INFO: 16 processes: 33 action cache hit, 9 internal, 7 linux-sandbox.
ERROR: Build did NOT complete successfully

@wep21 have you seen such errors before?

@wep21
Copy link
Contributor

wep21 commented Jan 5, 2025

@davidzchen Does this BUILD.bazel work on your environment?

# Copyright 2020 Google LLC
#
# 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.

# The ncurses C library and unit test.

load("//bazel:automake_substitution.bzl", "automake_substitution")
load("//bazel:pseudo_configure.bzl", "pseudo_configure")

package(default_visibility = ["//visibility:public"])

licenses(["notice"])

exports_files([
    "LICENSE",
    "include/Caps",
])

NCURSES_COPTS = [
    "-w",
    "-DTRACE",
    "-DHAVE_CONFIG_H",
    "-D_GNU_SOURCE",
    "-DNDEBUG",
]

CAPLIST = [
    "include/Caps",
    "include/Caps-ncurses",
]

CAPLIST_LOCATIONS = " ".join(["$(location :" + cap + ")" for cap in CAPLIST])

AUTOMAKE_SUBSTITUTIONS = {
    "NCURSES_MAJOR": "6",
    "NCURSES_MINOR": "4",
    "NCURSES_PATCH": "20221231",
    "NCURSES_MOUSE_VERSION": "2",
    "NCURSES_CONST": "const",
    "NCURSES_INLINE": "inline",
    "NCURSES_SBOOL": "char",
    "NCURSES_USE_DATABASE": "1",
    "NCURSES_USE_TERMCAP": "0",
    "NCURSES_XNAMES": "1",
    "HAVE_TERMIOS_H": "1",
    "HAVE_TCGETATTR": "1",
    "HAVE_TERMIO_H": "1",
    "NCURSES_EXT_COLORS": "0",
    "BROKEN_LINKER": "0",
    "cf_cv_enable_reentrant": "0",
    "NCURSES_TPARM_VARARGS": "1",
    "NCURSES_TPARM_ARG": "intptr_t",
    "HAVE_STDINT_H": "1",
    "HAVE_STDNORETURN_H": "1",
    "cf_cv_header_stdbool_h": "1",
    "NCURSES_OPAQUE": "0",
    "NCURSES_OPAQUE_FORM": "0",
    "NCURSES_OPAQUE_MENU": "0",
    "NCURSES_OPAQUE_PANEL": "0",
    "NCURSES_WATTR_MACROS": "1",
    "NCURSES_INTEROP_FUNCS": "1",
    "NCURSES_SIZE_T": "short",
    "NCURSES_CH_T": "cchar_t",
    "cf_cv_enable_lp64": "1",
    "cf_cv_type_of_bool": "unsigned char",
    "USE_CXX_BOOL": "defined(__cplusplus)",
    "NCURSES_EXT_FUNCS": "1",
    "NCURSES_LIBUTF8": "0",
    "NEED_WCHAR_H": "1",
    "NCURSES_WCHAR_T": "0",
    "NCURSES_OK_WCHAR_T": "",
    "NCURSES_CCHARW_MAX": "5",
    "NCURSES_WCWIDTH_GRAPHICS": "1",
    "GENERATED_EXT_FUNCS": "generated",
    "NCURSES_SP_FUNCS": "1",
    "cf_cv_1UL": "1U",
    "HAVE_VSSCANF": "1",
    "NCURSES_WINT_T": "0",
    "NCURSES_OSPEED": "short",
    "cf_cv_typeof_chtype": "cchar_t",
    "cf_cv_typeof_mmask_t": "unsigned",
    "NCURSES_WRAP_PREFIX": "_nc_",
    "EXP_WIN32_DRIVER": "0",
    "USE_WIDEC_SUPPORT": "1",
    "NCURSES_WIDECHAR": "1",
    "HAVE_WCHAR_H": "1",
    "HAVE_WCTYPE_H": "1",
    "HAVE_PUTWC": "1",
    "HAVE_BTOWC": "1",
    "HAVE_WCTOB": "1",
    "HAVE_WMEMCHR": "1",
    "HAVE_MBTOWC": "1",
    "HAVE_WCTOMB": "1",
    "HAVE_MBLEN": "1",
    "HAVE_MBRLEN": "1",
    "HAVE_MBRTOWC": "1",
    "HAVE_WCSRTOMBS": "1",
    "HAVE_MBSRTOWCS": "1",
    "HAVE_WCSTOMBS": "1",
    "HAVE_MBSTOWCS": "1",
    "NCURSES_MBSTATE_T": "1",
}

cc_library(
    name = "ncurses_headers",
    hdrs = glob(["include/*"]) + [
        # Generated files are not found by glob.
        "include/hashsize.h",
        "include/ncurses_cfg.h",
        "include/ncurses_def.h",
        "include/parametrized.h",
        "include/curses.h",
        "include/term.h",
        "include/ncurses_dll.h",
        "include/unctrl.h",
        "include/termcap.h",
        # Various source files include these, so call them headers.
        "ncurses/tinfo/doalloc.c",
        "ncurses/names.c",
    ],
    includes = [
        "include",
        "ncurses",
    ],
)

cc_library(
    name = "ncurses",
    srcs = glob(
        [
            "ncurses/base/*.c",
            "ncurses/*.c",
            "ncurses/*.h",
            "ncurses/tinfo/*.c",
            "ncurses/trace/*.c",
            "ncurses/tty/*.c",
            "ncurses/widechar/*.c",
        ],
        exclude = glob([
            "ncurses/base/lib_driver.c",
            "ncurses/base/sigaction.c",
            "ncurses/tinfo/make_keys.c",
            "ncurses/tinfo/tinfo_driver.c",
            "ncurses/tinfo/make_hash.c",
            "ncurses/report_offsets.c",
            "ncurses/report_hashing.c",
        ]),
    ) + [
        # Generated files are not found by glob.
        "ncurses/codes.c",
        "ncurses/comp_captab.c",
        "ncurses/comp_userdefs.c",
        "ncurses/fallback.c",
        "ncurses/init_keytry.h",
        "ncurses/lib_gen.c",
        "ncurses/lib_keyname.c",
        "ncurses/names.c",
        "ncurses/unctrl.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

# Common headers between form and menu.
cc_library(
    name = "mf_common",
    hdrs = [
        "menu/eti.h",
        "menu/mf_common.h",
    ],
    includes = ["menu"],
)

cc_library(
    name = "form",
    srcs = glob(["form/*.c"]) + [
        "form/form.priv.h",
        "ncurses/curses.priv.h",
    ],
    hdrs = ["form/form.h"],
    copts = NCURSES_COPTS,
    deps = [
        ":mf_common",
        ":ncurses",
    ],
)

cc_library(
    name = "menu",
    srcs = glob(["menu/*.c"]) + [
        "menu/menu.priv.h",
        "ncurses/curses.priv.h",
    ],
    hdrs = ["menu/menu.h"],
    copts = NCURSES_COPTS,
    deps = [
        ":mf_common",
        ":ncurses",
    ],
)

cc_library(
    name = "panel",
    srcs = glob(["panel/*.c"]) + [
        "ncurses/curses.priv.h",
        "panel/panel.priv.h",
    ],
    hdrs = [
        "panel/panel.h",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses"],
)

genrule(
    name = "fallback_c",
    srcs = ["misc/terminfo.src"],
    outs = ["ncurses/fallback.c"],
    cmd = "$(location :ncurses/tinfo/MKfallback.sh) /usr/share/terminfo $(location :misc/terminfo.src) $$(which tic) $$(which infocmp) > $@",
    tools = ["ncurses/tinfo/MKfallback.sh"],
)

cc_binary(
    name = "make_hash",
    srcs = [
        "ncurses/build.priv.h",
        "ncurses/curses.priv.h",
        "ncurses/tinfo/make_hash.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

genrule(
    name = "comp_captab_c",
    srcs = [
        "ncurses/tinfo/MKcaptab.awk",
        "include/Caps",
    ],
    outs = ["ncurses/comp_captab.c"],
    cmd = "cp -f $(location :make_hash) . && $(location :ncurses/tinfo/MKcaptab.sh) $$(which awk) 1 $(location :ncurses/tinfo/MKcaptab.awk) $(location :include/Caps) > $@",
    tools = [
        "ncurses/tinfo/MKcaptab.sh",
        ":make_hash",
    ],
)

genrule(
    name = "comp_userdefs_c",
    srcs = ["include/hashsize.h"] + CAPLIST,
    outs = ["ncurses/comp_userdefs.c"],
    cmd = "cp -f $(location :make_hash) . && $(location ncurses/tinfo/MKuserdefs.sh) $$(which awk) 1 " + CAPLIST_LOCATIONS + " > $@",
    tools = [
        "ncurses/tinfo/MKuserdefs.sh",
        ":make_hash",
    ],
)

genrule(
    name = "codes_c",
    srcs = [
        "ncurses/tinfo/MKcodes.awk",
        "include/Caps",
    ],
    outs = ["ncurses/codes.c"],
    cmd = "/usr/bin/env awk -f $(location ncurses/tinfo/MKcodes.awk) bigstrings=1 $(location :include/Caps) > $@",
)

genrule(
    name = "names_c",
    srcs = [
        "ncurses/tinfo/MKnames.awk",
        "include/Caps",
    ],
    outs = ["ncurses/names.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/tinfo/MKnames.awk) bigstrings=1 $(location :include/Caps) > $@",
)

genrule(
    name = "unctrl_c",
    srcs = [
        "ncurses/base/MKunctrl.awk",
    ],
    outs = ["ncurses/unctrl.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/base/MKunctrl.awk) bigstrings=1 > $@",
)

cc_binary(
    name = "make_keys",
    srcs = [
        "ncurses/build.priv.h",
        "ncurses/curses.priv.h",
        "ncurses/tinfo/make_keys.c",
    ],
    copts = NCURSES_COPTS,
    deps = [":ncurses_headers"],
)

genrule(
    name = "keys_list",
    srcs = ["include/Caps"],
    outs = ["keys.list"],
    cmd = "$(location :ncurses/tinfo/MKkeys_list.sh) $(location :include/Caps) | LC_ALL=C sort > $@",
    tools = ["ncurses/tinfo/MKkeys_list.sh"],
)

genrule(
    name = "lib_keyname_c",
    srcs = [
        "ncurses/base/MKkeyname.awk",
        "keys.list",
    ],
    outs = ["ncurses/lib_keyname.c"],
    cmd = "/usr/bin/env awk -f $(location :ncurses/base/MKkeyname.awk) bigstrings=1 $(location :keys.list) > $@",
)

automake_substitution(
    name = "curses_head",
    src = "include/curses.h.in",
    out = "include/curses.head",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "curses_dll",
    src = "include/ncurses_dll.h.in",
    out = "include/ncurses_dll.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "unctrl_h",
    src = "include/unctrl.h.in",
    out = "include/unctrl.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

automake_substitution(
    name = "termcap_h",
    src = "include/termcap.h.in",
    out = "include/termcap.h",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

genrule(
    name = "curses_h",
    srcs = [
        "include/curses.head",
        "include/curses.tail",
        "include/curses.wide",
    ] + CAPLIST,
    outs = ["include/curses.h"],
    cmd = "cat $(location :include/curses.head) > $@ && AWK=$$(which awk) $(location :include/MKkey_defs.sh) " + CAPLIST_LOCATIONS + " >> $@ && cat $(location :include/curses.wide) $(location :include/curses.tail) >> $@",
    tools = ["include/MKkey_defs.sh"],
)

genrule(
    name = "lib_gen_c",
    srcs = [
        "include/curses.h",
        "include/ncurses_cfg.h",
        "include/ncurses_def.h",
    ],
    outs = ["ncurses/lib_gen.c"],
    cmd = "$(location :ncurses/base/MKlib_gen.sh) \"$$(which cpp) -isystem $$(dirname $(location :include/ncurses_cfg.h))\" $$(which awk) generated < $(location :include/curses.h) > $@",
    tools = ["ncurses/base/MKlib_gen.sh"],
)

genrule(
    name = "hashsize_h",
    srcs = ["include/Caps"],
    outs = ["include/hashsize.h"],
    cmd = "$(location :include/MKhashsize.sh) $(location :include/Caps) > $@",
    tools = ["include/MKhashsize.sh"],
)

genrule(
    name = "init_keytry_h",
    srcs = ["keys.list"],
    outs = ["ncurses/init_keytry.h"],
    cmd = "$(location :make_keys) $(location :keys.list) > $@",
    tools = [":make_keys"],
)

automake_substitution(
    name = "mkterm_h_awk",
    src = "include/MKterm.h.awk.in",
    out = "include/MKterm.h.awk",
    substitutions = AUTOMAKE_SUBSTITUTIONS,
)

genrule(
    name = "term_h",
    srcs = [
        "include/MKterm.h.awk",
        "include/Caps",
    ],
    outs = ["include/term.h"],
    cmd = "/usr/bin/env awk -f $(location :include/MKterm.h.awk) $(location :include/Caps) > $@",
)

genrule(
    name = "parametrized_h",
    srcs = ["include/Caps"],
    outs = ["include/parametrized.h"],
    cmd = "(cd $$(dirname $(location :include/MKparametrized.sh)) && ./MKparametrized.sh) > $@",
    tools = ["include/MKparametrized.sh"],
)

genrule(
    name = "ncurses_def_h",
    srcs = ["include/ncurses_defs"],
    outs = ["include/ncurses_def.h"],
    cmd = "(cd $$(dirname $(location :include/MKncurses_def.sh)) && ./MKncurses_def.sh) > $@",
    tools = ["include/MKncurses_def.sh"],
)

pseudo_configure(
    name = "ncurses_cfg_h",
    src = "include/ncurses_cfg.hin",
    out = "include/ncurses_cfg.h",
    defs = [
        "HAVE_LONG_FILE_NAMES",
        "MIXEDCASE_FILENAMES",
        "HAVE_BIG_CORE",
        "PURE_TERMINFO",
        "USE_HOME_TERMINFO",
        "USE_ROOT_ENVIRON",
        "HAVE_UNISTD_H",
        "HAVE_REMOVE",
        "HAVE_UNLINK",
        "HAVE_LINK",
        "HAVE_SYMLINK",
        "USE_LINKS",
        "HAVE_LANGINFO_CODESET",
        "HAVE_FSEEKO",
        "STDC_HEADERS",
        "HAVE_SYS_TYPES_H",
        "HAVE_SYS_STAT_H",
        "HAVE_STDLIB_H",
        "HAVE_STRING_H",
        "HAVE_MEMORY_H",
        "HAVE_STRINGS_H",
        "HAVE_INTTYPES_H",
        "HAVE_STDINT_H",
        "HAVE_UNISTD_H",
        "SIZEOF_SIGNED_CHAR",
        "NCURSES_EXT_FUNCS",
        "HAVE_ASSUME_DEFAULT_COLORS",
        "HAVE_CURSES_VERSION",
        "HAVE_HAS_KEY",
        "HAVE_RESIZETERM",
        "HAVE_RESIZE_TERM",
        "HAVE_TERM_ENTRY_H",
        "HAVE_USE_DEFAULT_COLORS",
        "HAVE_USE_EXTENDED_NAMES",
        "HAVE_USE_SCREEN",
        "HAVE_USE_WINDOW",
        "HAVE_WRESIZE",
        "NCURSES_SP_FUNCS",
        "HAVE_TPUTS_SP",
        "NCURSES_EXT_PUTWIN",
        "NCURSES_NO_PADDING",
        "USE_SIGWINCH",
        "USE_ASSUMED_COLOR",
        "USE_HASHMAP",
        "GCC_SCANF",
        "GCC_PRINTF",
        "HAVE_NC_ALLOC_H",
        "HAVE_GETTIMEOFDAY",
        "STDC_HEADERS",
        "HAVE_DIRENT_H",
        "TIME_WITH_SYS_TIME",
        "HAVE_REGEX_H_FUNCS",
        "HAVE_FCNTL_H",
        "HAVE_GETOPT_H",
        "HAVE_LIMITS_H",
        "HAVE_LOCALE_H",
        "HAVE_MATH_H",
        "HAVE_POLL_H",
        "HAVE_SYS_IOCTL_H",
        "HAVE_SYS_PARAM_H",
        "HAVE_SYS_POLL_H",
        "HAVE_SYS_SELECT_H",
        "HAVE_SYS_TIME_H",
        "HAVE_SYS_TIMES_H",
        "HAVE_TTYENT_H",
        "HAVE_UNISTD_H",
        "HAVE_WCTYPE_H",
        "HAVE_UNISTD_H",
        "HAVE_GETOPT_H",
        "HAVE_GETOPT_HEADER",
        "DECL_ENVIRON",
        "HAVE_ENVIRON",
        "HAVE_PUTENV",
        "HAVE_SETENV",
        "HAVE_STRDUP",
        "HAVE_SYS_TIME_SELECT",
        "HAVE_GETCWD",
        "HAVE_GETEGID",
        "HAVE_GETEUID",
        "HAVE_GETOPT",
        "HAVE_GETTTYNAM",
        "HAVE_LOCALECONV",
        "HAVE_POLL",
        "HAVE_PUTENV",
        "HAVE_REMOVE",
        "HAVE_SELECT",
        "HAVE_SETBUF",
        "HAVE_SETBUFFER",
        "HAVE_SETENV",
        "HAVE_SETVBUF",
        "HAVE_SIGACTION",
        "HAVE_STRDUP",
        "HAVE_STRSTR",
        "HAVE_SYSCONF",
        "HAVE_TCGETPGRP",
        "HAVE_TIMES",
        "HAVE_TSEARCH",
        "HAVE_VSNPRINTF",
        "HAVE_ISASCII",
        "HAVE_NANOSLEEP",
        "HAVE_TERMIO_H",
        "HAVE_TERMIOS_H",
        "HAVE_UNISTD_H",
        "HAVE_SYS_IOCTL_H",
        "HAVE_TCGETATTR",
        "HAVE_VSSCANF",
        "HAVE_UNISTD_H",
        "HAVE_MKSTEMP",
        "HAVE_SIZECHANGE",
        "HAVE_WORKING_POLL",
        "HAVE_VA_COPY",
        "HAVE_UNISTD_H",
        "HAVE_FORK",
        "HAVE_VFORK",
        "HAVE_WORKING_VFORK",
        "HAVE_WORKING_FORK",
        "USE_FOPEN_BIN_R",
        "USE_XTERM_PTY",
        "HAVE_TYPEINFO",
        "HAVE_IOSTREAM",
        "IOSTREAM_NAMESPACE",
        "CPP_HAS_STATIC_CAST",
        "HAVE_SLK_COLOR",
        "HAVE_PANEL_H",
        "HAVE_LIBPANEL",
        "HAVE_MENU_H",
        "HAVE_LIBMENU",
        "HAVE_FORM_H",
        "HAVE_LIBFORM",
        "NCURSES_OSPEED_COMPAT",
        "HAVE_CURSES_DATA_BOOLNAMES",
        "NCURSES_WIDECHAR",
        "USE_WIDEC_SUPPORT",
        "HAVE_WCHAR_H",
        "HAVE_WCTYPE_H",
        "HAVE_PUTWC",
        "HAVE_BTOWC",
        "HAVE_WCTOB",
        "HAVE_WMEMCHR",
        "HAVE_MBTOWC",
        "HAVE_WCTOMB",
        "HAVE_MBLEN",
        "HAVE_MBRLEN",
        "HAVE_MBRTOWC",
        "HAVE_WCSRTOMBS",
        "HAVE_MBSRTOWCS",
        "HAVE_WCSTOMBS",
        "HAVE_MBSTOWCS",
        "NEED_WCHAR_H",
    ],
    mappings = {
        "NC_CONFIG_H": "",
        "PACKAGE": '"ncurses"',
        "NCURSES_VERSION": '"6.4"',
        "NCURSES_PATCHDATE": "20200212",
        "SYSTEM_NAME": '"linux-gnu"',
        "TERMINFO_DIRS": r'"\/usr\/share\/terminfo"',
        "TERMINFO": r'"\/usr\/share\/terminfo"',
        "RGB_PATH": r'"\/usr\/share\/X11\/rgb.txt"',
        "NCURSES_WRAP_PREFIX": '"_nc_"',
        "GCC_SCANFLIKE(fmt,var)": "__attribute__((format(scanf,fmt,var)))",
        "GCC_PRINTFLIKE(fmt,var)": "__attribute__((format(printf,fmt,var)))",
        "GCC_UNUSED": "__attribute__((unused))",
        "GCC_NORETURN": "__attribute__((noreturn))",
        "SIG_ATOMIC_T": "volatile sig_atomic_t",
        "USE_OPENPTY_HEADER": "<pty.h>",
        "NCURSES_PATHSEP": "0x3a",
        "NCURSES_VERSION_STRING": '"6.4.20221231"',
        # "mbstate_t": "int",
    },
)

@davidzchen
Copy link
Member Author

That worked. Thank you very much!

Let's go ahead and create a new version of the ncurses module in BCR.

meteorcloudy pushed a commit that referenced this issue Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants